Annotation of XNU/bsd/netat/ddp_lap.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) 1988, 1989, 1993-1998 Apple Computer, Inc. 
        !            24:  */
        !            25: 
        !            26: /* at_elap.c: 2.0, 1.29; 10/4/93; Apple Computer, Inc. */
        !            27: 
        !            28: /* This is the file which implements all the streams driver 
        !            29:  * functionality required for EtherTalk.
        !            30:  */
        !            31: 
        !            32: /* revision history 
        !            33: 
        !            34:  03-14-94  jjs         Changed all functions which assumed only one port would
        !            35:                ever be used.  Added validate_msg_size, changed elap_online
        !            36:                to work with the h/w name only (e.g. 'et2').
        !            37: 
        !            38:  Modified for MP, 1996 by Tuyen Nguyen
        !            39:  Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
        !            40: 
        !            41: */
        !            42: 
        !            43: #define RESOLVE_DBG                            /* for debug.h global resolution */
        !            44: #include <sys/errno.h>
        !            45: #include <sys/types.h>
        !            46: #include <sys/param.h>
        !            47: #include <machine/spl.h>
        !            48: #include <sys/systm.h>
        !            49: #include <sys/kernel.h>
        !            50: #include <sys/proc.h>
        !            51: #include <sys/filedesc.h>
        !            52: #include <sys/fcntl.h>
        !            53: #include <sys/mbuf.h>
        !            54: #include <sys/ioctl.h>
        !            55: #include <sys/socket.h>
        !            56: #include <sys/socketvar.h>
        !            57: #include <sys/malloc.h>
        !            58: #include <sys/sockio.h>
        !            59: 
        !            60: #include <net/if.h>
        !            61: #include <net/if_types.h>
        !            62: 
        !            63: #include <netat/sysglue.h>
        !            64: #include <netat/appletalk.h>
        !            65: #include <netat/at_var.h>
        !            66: #include <netat/ddp.h>
        !            67: #include <netat/lap.h>
        !            68: #include <netat/routing_tables.h>     /* rtmp+zip table structs  */
        !            69: #include <netat/zip.h>
        !            70: #include <netat/nbp.h>
        !            71: #include <netat/at_snmp.h>
        !            72: #include <netat/at_pcb.h>
        !            73: #include <netat/at_aarp.h>
        !            74: #include <netat/debug.h>
        !            75: #include <netat/at_config.h>
        !            76: 
        !            77: /* globals */
        !            78: 
        !            79: at_ifaddr_t at_interfaces[IF_TOTAL_MAX];
        !            80:        /* index for at_interfaces is not important */
        !            81: at_ifaddr_t  *ifID_table[IF_TOTAL_MAX];
        !            82:        /* the table of ifID structures, one per interface 
        !            83:           (not just ethernet), indexed by DDP port
        !            84:         * NOTE: for MH, entry 0 in this table is 
        !            85:         *       now defined to be the default I/F
        !            86:         */
        !            87: at_ifaddr_t  *ifID_home;
        !            88:        /* always ifID_table[IFID_HOME] for now, but will be used for
        !            89:           dynamic "home port" assignment, later */
        !            90: 
        !            91: at_state_t     at_state;               /* global state of AT network */
        !            92: if_types_t if_types[IF_TYPENO_CNT] = {{ IFT_ETHER, IF_TOTAL_MAX }};
        !            93: 
        !            94: snmpFlags_t snmpFlags;
        !            95: 
        !            96: int xpatcnt = 0;
        !            97: 
        !            98:        /* snmp defines */
        !            99: #define MAX_BUFSIZE            8192   
        !           100: #define MAX_RTMP               (MAX_BUFSIZE/sizeof(RT_entry)-1)
        !           101: #define MAX_NBP                \
        !           102:        ((MAX_BUFSIZE - SNMP_NBP_HEADER_SIZE)/sizeof(snmpNbpEntry_t)-1)
        !           103: #define MAX_NBP_BYTES  (MAX_NBP * sizeof(snmpNbpEntry_t))
        !           104: #define MAX_ZIP                        (MAX_BUFSIZE/sizeof(ZT_entry)-1)
        !           105: #define MAX_RTMP_BYTES (MAX_RTMP * sizeof(RT_entry))
        !           106: #define MAX_ZIP_BYTES  (MAX_ZIP * sizeof(ZT_entry))
        !           107: 
        !           108: /* externs */
        !           109: extern TAILQ_HEAD(name_registry, _nve_) name_registry;
        !           110: extern snmpStats_t     snmpStats;
        !           111: extern atlock_t ddpinp_lock;
        !           112: extern atlock_t arpinp_lock;
        !           113: extern short appletalk_inited;
        !           114: extern int adspInited;
        !           115: extern struct atpcb ddp_head;
        !           116: extern at_ddp_stats_t at_ddp_stats;
        !           117: 
        !           118: /* protos */
        !           119: extern snmpAarpEnt_t * getAarp(int *);
        !           120: extern int setLocalZones(at_nbptuple_t * , int);
        !           121: extern int getRTRLocalZone(if_zone_t *);
        !           122: extern void nbp_shutdown(), routershutdown(), ddp_brt_shutdown();
        !           123: extern void ddp_brt_init(), rtmp_init(), rtmp_input();
        !           124: extern rtmp_router_start(at_kern_err_t *);
        !           125: static void getIfNames(if_name_t *);
        !           126: static void add_route();
        !           127: static int set_zones();
        !           128: void elap_offline();
        !           129: static int elap_online1(), re_aarp();
        !           130: int at_reg_mcast(), at_unreg_mcast();
        !           131: void  AARPwakeup(), ZIPwakeup();
        !           132: void ddp_bit_reverse(), ddp_shutdown();
        !           133: static void elap_hangup();
        !           134: static getSnmpCfg();
        !           135: 
        !           136: at_ifaddr_t *find_ifID(if_name)
        !           137:        char    *if_name;
        !           138: {
        !           139:        int pat_id;
        !           140:          
        !           141:        if (strlen(if_name))
        !           142:                for (pat_id=0; pat_id < xpatcnt; pat_id++) {
        !           143:                        if (!strcmp(at_interfaces[pat_id].ifName, if_name))
        !           144:                                return(&at_interfaces[pat_id]);
        !           145:                }
        !           146: 
        !           147:        return((at_ifaddr_t *)NULL);
        !           148: }
        !           149: 
        !           150: static int validate_msg_size(m, gref, elapp)
        !           151:        register gbuf_t *m;
        !           152:        gref_t          *gref;
        !           153:        at_ifaddr_t **elapp;
        !           154: 
        !           155: /* checks ioctl message type for minimum expected message size & 
        !           156:    sends error back if size invalid
        !           157: */
        !           158: {
        !           159:        register ioc_t *iocbp;
        !           160:        register at_if_cfg_t *cfgp;
        !           161:        int i, size = 1;
        !           162:        
        !           163:        *elapp = NULL;          
        !           164:        iocbp = (ioc_t *) gbuf_rptr(m);
        !           165: 
        !           166:        dPrintf(D_M_ELAP, D_L_INFO, ("validate_msg_size: ioc_cmd = %d\n", 
        !           167:                                     iocbp->ioc_cmd));
        !           168:        switch (iocbp->ioc_cmd) {
        !           169:                case LAP_IOC_ADD_ROUTE:
        !           170:                        size = sizeof(RT_entry);
        !           171:                        break;
        !           172:                case LAP_IOC_ADD_ZONE:
        !           173:                        size = sizeof(if_zone_info_t);
        !           174:                        break;
        !           175:                case LAP_IOC_GET_ROUTE:
        !           176:                        size = sizeof(RT_entry);
        !           177:                        break;
        !           178:                case LAP_IOC_GET_ZONE:
        !           179:                        size = sizeof(ZT_entryno);
        !           180:                        break;
        !           181:                case LAP_IOC_SNMP_GET_CFG:
        !           182:                case LAP_IOC_SNMP_GET_AARP:
        !           183:                case LAP_IOC_SNMP_GET_ZIP:
        !           184:                case LAP_IOC_SNMP_GET_RTMP:
        !           185:                case LAP_IOC_SNMP_GET_NBP:
        !           186:                        size = sizeof(int);
        !           187:                        break;
        !           188:                case LAP_IOC_GET_LOCAL_ZONE:
        !           189:                        size = sizeof(if_zone_t);
        !           190:                        break;
        !           191:                case LAP_IOC_CHECK_STATE:
        !           192:                        size = 1;
        !           193:                        break;
        !           194: 
        !           195:                case ELAP_IOC_GET_STATS:
        !           196:                case LAP_IOC_SNMP_GET_DDP:
        !           197:                case LAP_IOC_GET_IF_NAMES:
        !           198:                        size = 0;
        !           199:                        break;
        !           200:                        
        !           201:                /* these ioctls  send variable length data */
        !           202:                case LAP_IOC_SET_LOCAL_ZONES:
        !           203:                        size = -1;
        !           204:                        break;
        !           205:                default:
        !           206:                        dPrintf(D_M_ELAP, D_L_ERROR, ("validate_msg_size: unknown ioctl\n"));
        !           207:                        goto error;
        !           208:        }
        !           209: 
        !           210:        if (size == 0) {                                /* a non-data ioctl */
        !           211:                return(0);
        !           212:        }
        !           213: 
        !           214:        if (gbuf_cont(m) != NULL) {
        !           215:                i = gbuf_len(gbuf_cont(m));
        !           216:                if (size == -1)
        !           217:                        if (i >1)
        !           218:                                return(0);
        !           219:                        else
        !           220:                                goto error;
        !           221:        }
        !           222:        if (iocbp->ioc_count < size || (gbuf_cont(m) == NULL) || i < size) {
        !           223:                dPrintf(D_M_ELAP, D_L_ERROR,
        !           224:                        ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n",
        !           225:                         size, iocbp->ioc_count,
        !           226:                         gbuf_cont(m)? 'Y' : 'N', i));
        !           227:                goto error;
        !           228:        }
        !           229:        else
        !           230:                return(0);
        !           231: error:
        !           232:        ioc_ack(EMSGSIZE, m, gref);
        !           233:        return (EMSGSIZE);
        !           234: } /* validate_msg_size */
        !           235: 
        !           236: int lap_online(elapp, cfgp)
        !           237:      at_ifaddr_t *elapp;
        !           238:      at_if_cfg_t *cfgp;
        !           239: {
        !           240:        int error;
        !           241: 
        !           242:        if (elapp->ifState != LAP_OFFLINE) {
        !           243:                return(EALREADY);
        !           244:        }
        !           245: 
        !           246:        elapp->flags = 0;
        !           247:        if (cfgp->flags & ELAP_CFG_HOME) {
        !           248:                if (ifID_home)  {
        !           249:                        /* only 1 home allowed! */
        !           250:                        return(EEXIST);
        !           251:                }
        !           252:                dPrintf(D_M_ELAP, D_L_STARTUP, 
        !           253:                        ("elap_wput home I/F:%s\n", cfgp->ifr_name));
        !           254:                elapp->flags |= ELAP_CFG_HOME;
        !           255:        }
        !           256: 
        !           257:        if (MULTIPORT_MODE) {
        !           258:                elapp->flags |= ELAP_CFG_ZONELESS;
        !           259:                if (ROUTING_MODE && cfgp->netStart)
        !           260:                        elapp->flags |= ELAP_CFG_SEED;
        !           261:        }
        !           262: 
        !           263:        if (!DEFAULT_ZONE(&cfgp->zonename) &&
        !           264:            (elapp->flags & ELAP_CFG_HOME) || MULTIHOME_MODE) {
        !           265:                elapp->startup_zone = cfgp->zonename;
        !           266:        }
        !           267: 
        !           268:        if (elapp->flags & ELAP_CFG_SEED) {
        !           269:                dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
        !           270:                        ("elap_wput: found to be seed\n"));
        !           271:                elapp->ifThisCableStart = cfgp->netStart;
        !           272:                elapp->ifThisCableEnd   = cfgp->netEnd;
        !           273:        }
        !           274:        else {
        !           275:                dPrintf(D_M_ELAP,D_L_ERROR, 
        !           276:                        ("elap_wput: we believe we're not seed\n"));
        !           277:                /* from ELAP_IOC_SET_CFG */
        !           278:                if (ATALK_VALUE(cfgp->node)) {
        !           279:                        u_short initial_net;
        !           280:                        u_char  initial_node;
        !           281: 
        !           282:                        initial_node = cfgp->node.s_node;
        !           283:                        initial_net = cfgp->node.s_net;
        !           284:                        if ((initial_node<0xfe) && (initial_node>0) &&
        !           285:                            !((initial_net == 0) ||
        !           286:                              ((initial_net >= DDP_STARTUP_LOW)&&
        !           287:                               (initial_net <= DDP_STARTUP_HIGH)))) {
        !           288: 
        !           289:                                elapp->initial_addr = cfgp->node;
        !           290:                        }
        !           291:                }
        !           292:        }
        !           293: 
        !           294:        elapp->startup_error = 0;
        !           295:        elapp->startup_inprogress = FALSE;
        !           296:        if ((error = elap_online1(elapp)))
        !           297:                ddp_rem_if(elapp);
        !           298:        else 
        !           299:                if (!(MULTIPORT_MODE) &&
        !           300:                    elapp->ifZoneName.len == 1 &&
        !           301:                    elapp->ifZoneName.str[0] == '*' &&
        !           302:                    !DEFAULT_ZONE(&cfgp->zonename)) {
        !           303:                        nbp_add_multicast(&cfgp->zonename, elapp);
        !           304:                }
        !           305:        return(error);
        !           306: } /* lap_online */
        !           307: 
        !           308: /***********************************************************************
        !           309:  * elap_wput()
        !           310:  *
        !           311:  **********************************************************************/
        !           312: int elap_wput(gref, m)
        !           313:      gref_t *gref;
        !           314:      register gbuf_t   *m;
        !           315: {
        !           316:        at_ifaddr_t     *elapp;
        !           317:        register ioc_t          *iocbp;
        !           318:        register at_if_cfg_t    *cfgp;
        !           319:        at_elap_stats_t         *statsp;
        !           320:        int error, i;
        !           321:        int                     (*func)();
        !           322:        gbuf_t          *tmpm;
        !           323:        at_ifaddr_t *patp;
        !           324: 
        !           325: 
        !           326:        switch (gbuf_type(m)) {
        !           327:        case MSG_DATA:
        !           328:                gbuf_freem(m);
        !           329:                dPrintf(D_M_ELAP,D_L_ERROR,
        !           330:                        ("Output data to control channel is ignored\n"));
        !           331:        break;
        !           332: 
        !           333:        case MSG_IOCTL:
        !           334:                iocbp = (ioc_t *) gbuf_rptr(m);
        !           335: 
        !           336:                if (validate_msg_size(m, gref, &elapp))
        !           337:                        break;  
        !           338: 
        !           339:                if (elapp)
        !           340:                        cfgp = (at_if_cfg_t*) gbuf_rptr(gbuf_cont(m));
        !           341: 
        !           342:                if (LAP_IOC_MYIOCTL(iocbp->ioc_cmd) || 
        !           343:                    ELAP_IOC_MYIOCTL(iocbp->ioc_cmd)) {
        !           344: 
        !           345:                        switch (iocbp->ioc_cmd) {
        !           346: 
        !           347:                        case LAP_IOC_CHECK_STATE:
        !           348: #ifdef APPLETALK_DEBUG
        !           349:                                kprintf("LAP_IOC_CHECK_STATE\n");
        !           350: #endif
        !           351:                                error = (!(at_state.flags & AT_ST_STARTED))?
        !           352:                                                ENOTREADY : 0;
        !           353:                                if (error == 0) {
        !           354:                                        int size;
        !           355:                                        dPrintf(D_M_ELAP,D_L_INFO,
        !           356:                                                ("elap_wput: CHECK_STATE 1\n"));
        !           357: 
        !           358:                                        /* re-use gbuf */
        !           359:                                        tmpm = gbuf_cont(m);
        !           360:                                        gbuf_wset(tmpm, 0);
        !           361: 
        !           362:                                        size = list_pids((int *)gbuf_rptr(tmpm), 
        !           363:                                                         10); /* *** 10 just for now *** */
        !           364:                                        gbuf_wset(tmpm, (size * sizeof(int)));
        !           365:                                        gbuf_set_type(tmpm, MSG_DATA);
        !           366:                                        ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(tmpm);
        !           367:                                        ioc_ack(0, m, gref);
        !           368:                                } else {
        !           369:                                        dPrintf(D_M_ELAP,D_L_INFO,
        !           370:                                                ("elap_wput: CHECK_STATE 2\n"));
        !           371:                                        ioc_ack(error, m, gref);
        !           372:                                }
        !           373:                                break;
        !           374: 
        !           375:                        case ELAP_IOC_GET_STATS:
        !           376: #ifdef APPLETALK_DEBUG
        !           377:                                kprintf("LAP_IOC_GET_STATS\n");
        !           378: #endif
        !           379:                                if ( (gbuf_cont(m) == NULL)
        !           380:                                     || (elapp = find_ifID(gbuf_rptr(gbuf_cont(m)))) == NULL) {
        !           381:                                        ioc_ack(EINVAL, m, gref);
        !           382:                                        break;
        !           383:                                }
        !           384:                                gbuf_freem(gbuf_cont(m));
        !           385:                                if ((gbuf_cont(m) =gbuf_alloc(sizeof(at_elap_stats_t), 
        !           386:                                        PRI_MED)) == NULL) {
        !           387:                                        ioc_ack(ENOBUFS, m, gref);
        !           388:                                        break;
        !           389:                                }
        !           390:                                statsp = ((at_elap_stats_t *)gbuf_rptr(gbuf_cont(m)));
        !           391:                                *statsp = elapp->stats;
        !           392:                                gbuf_wset(gbuf_cont(m),sizeof(at_elap_stats_t));
        !           393:                                iocbp->ioc_count = sizeof(at_elap_stats_t);
        !           394:                                ioc_ack(0, m, gref);
        !           395:                                break;
        !           396: 
        !           397:                        case LAP_IOC_ADD_ZONE:
        !           398: #ifdef APPLETALK_DEBUG
        !           399:                                kprintf("LAP_IOC_ADD_ZONE\n");
        !           400: #endif
        !           401:                                i = set_zones((if_zone_info_t *)gbuf_rptr(gbuf_cont(m)));
        !           402:                                ioc_ack(i, m, gref);
        !           403:                                break;
        !           404: 
        !           405:                        case LAP_IOC_ADD_ROUTE:
        !           406: #ifdef APPLETALK_DEBUG
        !           407:                                kprintf("LAP_IOC_ADD_ROUTE\n");
        !           408: #endif
        !           409:                                add_route((RT_entry *)gbuf_rptr(gbuf_cont(m)));
        !           410:                                ioc_ack(0, m, gref);
        !           411:                                break;
        !           412: 
        !           413:                        case LAP_IOC_GET_ZONE:
        !           414: #ifdef APPLETALK_DEBUG
        !           415:                          kprintf("LAP_IOC_GET_ZONE\n");
        !           416: #endif
        !           417:                          /* return next ZT_entryno from ZT_table 
        !           418:                             a pointer to the struct ZT_entryno is passed down from
        !           419:                             user space and the first byte is cast to a int, if
        !           420:                             this int is non-zero, then the first ZT_entry is
        !           421:                             returned and subsequent calls with a zero value
        !           422:                             will return the next entry in the table. The next
        !           423:                             read after the last valid entry will return EINVAL
        !           424:                          */
        !           425:                        {
        !           426:                                ZT_entryno *pZTe;
        !           427: 
        !           428:                                i =  *(int *)gbuf_rptr(gbuf_cont(m));
        !           429:                                gbuf_freem(gbuf_cont(m));
        !           430:                                gbuf_cont(m) = NULL;
        !           431: 
        !           432:                                pZTe = zt_getNextZone(i);
        !           433:                                if (pZTe) {
        !           434:                                        if ((gbuf_cont(m) = gbuf_alloc(sizeof(ZT_entryno), PRI_MED)) == NULL) {
        !           435:                                                ioc_ack(ENOBUFS, m, gref);
        !           436:                                                break;
        !           437:                                        }       
        !           438:                                        *(ZT_entryno *)gbuf_rptr(gbuf_cont(m)) = *pZTe;
        !           439:                                        gbuf_wset(gbuf_cont(m),sizeof(ZT_entryno));
        !           440:                                        iocbp->ioc_count = sizeof(ZT_entryno);
        !           441:                                        ioc_ack(0, m, gref);
        !           442:                                }
        !           443:                                else
        !           444:                                        ioc_ack(EINVAL, m, gref);
        !           445:                        }
        !           446:                                break;
        !           447:                        case LAP_IOC_GET_LOCAL_ZONE:
        !           448: #ifdef APPLETALK_DEBUG
        !           449:                                kprintf("LAP_IOC_GET_LOCAL_ZONE\n");
        !           450: #endif
        !           451:                                if (!MULTIPORT_MODE) {
        !           452:                                        ioc_ack(EPERM, m, gref);
        !           453:                                        break;
        !           454:                                }
        !           455:                        {
        !           456:                                if_zone_t        *ifz;
        !           457:                                int zone;
        !           458: 
        !           459:                                zone =  ((if_zone_t *)gbuf_rptr(gbuf_cont(m)))->ifzn.zone;
        !           460:                                gbuf_freem(gbuf_cont(m));
        !           461:                                gbuf_cont(m) = NULL;
        !           462:                                if ((gbuf_cont(m) = gbuf_alloc(sizeof(if_zone_t), PRI_MED)) == NULL) {
        !           463:                                        ioc_ack(ENOBUFS, m, gref);
        !           464:                                        break;
        !           465:                                }       
        !           466:                                ifz = (if_zone_t *)gbuf_rptr(gbuf_cont(m));
        !           467:                                ifz->ifzn.zone = zone;
        !           468:                                getRTRLocalZone(ifz);
        !           469:                                gbuf_wset(gbuf_cont(m),sizeof(*ifz));
        !           470:                                iocbp->ioc_count = sizeof(*ifz);
        !           471:                        }
        !           472:                                ioc_ack(0, m, gref);
        !           473:                                break;
        !           474:                        case LAP_IOC_GET_ROUTE:
        !           475: #ifdef APPLETALK_DEBUG
        !           476:                                kprintf("LAP_IOC_GET_ROUTE\n");
        !           477: #endif
        !           478:                                /* return next RT_entry from RT_table 
        !           479:                                 * a pointer to the struct RT_entry is
        !           480:                                 * passed down from user space and the first
        !           481:                                 * byte is cast to a int, if this int is
        !           482:                                 * non-zero, then the first RT_entry is
        !           483:                                 * returned and subsequent calls with a
        !           484:                                 * zero value will return the next entry in
        !           485:                                 * the table. The next read after the last
        !           486:                                 * valid entry will return EINVAL
        !           487:                                 */
        !           488:                        {
        !           489:                                RT_entry *pRT;
        !           490: 
        !           491:                                i =  *(int *)gbuf_rptr(gbuf_cont(m));
        !           492:                                gbuf_freem(gbuf_cont(m));
        !           493:                                gbuf_cont(m) = NULL;
        !           494: 
        !           495:                                pRT = rt_getNextRoute(i);
        !           496:                                if (pRT) {
        !           497:                                        if ((gbuf_cont(m) = gbuf_alloc(sizeof(RT_entry), PRI_MED)) == NULL) {
        !           498:                                                ioc_ack(ENOBUFS, m, gref);
        !           499:                                                break;
        !           500:                                        }       
        !           501:                                        *(RT_entry *)gbuf_rptr(gbuf_cont(m)) = *pRT;
        !           502:                                        gbuf_wset(gbuf_cont(m),sizeof(RT_entry));
        !           503:                                        iocbp->ioc_count = sizeof(RT_entry);
        !           504:                                        ioc_ack(0, m, gref);
        !           505:                                }
        !           506:                                else
        !           507:                                        ioc_ack(EINVAL, m, gref);
        !           508:                        }
        !           509:                                break;
        !           510:                        
        !           511:                        case LAP_IOC_SNMP_GET_DDP:
        !           512: #ifdef APPLETALK_DEBUG
        !           513:                                kprintf("LAP_IOC_SNMP_GET_DDP\n");
        !           514: #endif
        !           515:                                if (!(at_state.flags & AT_ST_STARTED)) {
        !           516:                                        ioc_ack(ENOTREADY, m, gref);
        !           517:                                        break;
        !           518:                                }
        !           519:                                if ((gbuf_cont(m) = gbuf_alloc(sizeof(snmpStats_t), 
        !           520:                                                PRI_MED)) == NULL) {
        !           521:                                        ioc_ack(ENOBUFS, m, gref);
        !           522:                                        break;
        !           523:                                }
        !           524:                                
        !           525:                                *(snmpStats_t *)gbuf_rptr(gbuf_cont(m)) = snmpStats;
        !           526:                                gbuf_wset(gbuf_cont(m),sizeof(snmpStats));
        !           527:                                iocbp->ioc_count = sizeof(snmpStats);
        !           528:                                ioc_ack(0, m, gref);
        !           529:                                break;
        !           530:                        case LAP_IOC_SNMP_GET_CFG:
        !           531: #ifdef APPLETALK_DEBUG
        !           532:                                kprintf("LAP_IOC_SNMP_GET_CFG\n");
        !           533: #endif
        !           534:                        {
        !           535:                                int i,size;
        !           536:                                snmpCfg_t       snmp;
        !           537: 
        !           538:                                i =  *(int *)gbuf_rptr(gbuf_cont(m));
        !           539:                                gbuf_freem(gbuf_cont(m));
        !           540:                                gbuf_cont(m) = NULL;
        !           541:                                if (!(at_state.flags & AT_ST_STARTED)) {
        !           542:                                        /* if stack down */
        !           543:                                        iocbp->ioc_count = 0;
        !           544:                                        ioc_ack(ENOTREADY, m, gref);
        !           545:                                        dPrintf(D_M_ELAP_LOW, D_L_INFO,
        !           546:                                                ("elap_wput: cfg req, stack down\n"));
        !           547:                                        break;
        !           548:                                }
        !           549:                                if (i == UPDATE_IF_CHANGED && 
        !           550:                                        !(at_state.flags & AT_ST_IF_CHANGED)) {
        !           551:                                        iocbp->ioc_count = 0;
        !           552:                                        ioc_ack(0, m, gref);
        !           553:                                        dPrintf(D_M_ELAP_LOW, D_L_INFO,
        !           554:                                                ("elap_wput: cfg req, unchanged\n"));
        !           555:                                        break;
        !           556:                                }
        !           557:                                dPrintf(D_M_ELAP_LOW, D_L_INFO,
        !           558:                                        ("elap_wput: cfg req, changed\n"));
        !           559: 
        !           560:                                if (getSnmpCfg(&snmp)) {
        !           561:                                        dPrintf(D_M_ELAP,D_L_ERROR,
        !           562:                                                ("elap_wput:SNMP_GET_CFG error\n"));
        !           563:                                        ioc_ack(EOPNOTSUPP, m, gref);
        !           564:                                        break;
        !           565:                                }
        !           566:                                        /* send up only used part of table */
        !           567:                                size = sizeof(snmp) - 
        !           568:                                           sizeof(snmpIfCfg_t) * (MAX_IFS - snmp.cfg_ifCnt);
        !           569: 
        !           570:                                if ((gbuf_cont(m) = gbuf_alloc(size, PRI_MED)) == NULL) {
        !           571:                                        ioc_ack(ENOBUFS, m, gref);
        !           572:                                        break;
        !           573:                                }
        !           574:                                bcopy(&snmp,gbuf_rptr(gbuf_cont(m)),size);
        !           575:                                gbuf_wset(gbuf_cont(m),size);
        !           576:                                iocbp->ioc_count = size;
        !           577:                                at_state.flags &= ~AT_ST_IF_CHANGED;
        !           578:                                ioc_ack(0, m, gref);
        !           579:                        }
        !           580:                        break;
        !           581: 
        !           582:                        case LAP_IOC_SNMP_GET_AARP:
        !           583:                        {
        !           584:                                snmpAarpEnt_t *snmpp;
        !           585:                                int bytes;
        !           586: #ifdef APPLETALK_DEBUG
        !           587:                                kprintf("LAP_IOC_SNMP_GET_AARP\n");
        !           588: #endif
        !           589:                                i =  *(int *)gbuf_rptr(gbuf_cont(m));
        !           590:                                gbuf_freem(gbuf_cont(m));
        !           591:                                gbuf_cont(m) = NULL;
        !           592:                                dPrintf(D_M_ELAP,D_L_INFO,
        !           593:                                        ("elap_wput:calling getarp,i=%d\n", i));
        !           594:                                snmpp = getAarp(&i); 
        !           595:                                bytes = i * sizeof(snmpAarpEnt_t);
        !           596:                                dPrintf(D_M_ELAP,D_L_INFO,
        !           597:                                        ("elap_wput:getarp returned, i=%d,bytes=%d\n", 
        !           598:                                        i, bytes));
        !           599:                                if (snmpp) {
        !           600:                                        if ((gbuf_cont(m) = gbuf_alloc(bytes, PRI_MED)) == NULL) {
        !           601:                                                ioc_ack(ENOBUFS, m, gref);
        !           602:                                                break;
        !           603:                                        }       
        !           604:                                        bcopy(snmpp, gbuf_rptr(gbuf_cont(m)), bytes);
        !           605:                                        gbuf_wset(gbuf_cont(m),bytes);
        !           606:                                        iocbp->ioc_count = bytes;
        !           607:                                        ioc_ack(0, m, gref);
        !           608:                                }
        !           609:                                else
        !           610:                                        ioc_ack(EOPNOTSUPP, m, gref);
        !           611:                        }
        !           612:                        break;
        !           613: 
        !           614:                        case LAP_IOC_SNMP_GET_ZIP:
        !           615: #ifdef APPLETALK_DEBUG
        !           616:                                kprintf("LAP_IOC_SNMP_GET_ZIP\n");
        !           617: #endif
        !           618:                        { /* matching brace NOT in this case */
        !           619:                                register int i,j;
        !           620:                                register int size, total, tabsize;
        !           621:                                gbuf_t  *mn;            /* new gbuf */
        !           622:                                gbuf_t  *mo;            /* old gbuf */
        !           623:                                gbuf_t  *mt;            /* temp */
        !           624:                                snmpNbpTable_t          *nbp;
        !           625: 
        !           626:                                i =  *(int *)gbuf_rptr(gbuf_cont(m));
        !           627:                                gbuf_freem(gbuf_cont(m));
        !           628:                                gbuf_cont(m) = NULL;
        !           629:                                if (!(at_state.flags & AT_ST_STARTED)) {
        !           630:                                        ioc_ack(ENOTREADY, m, gref);
        !           631:                                        break;
        !           632:                                }
        !           633:                                if (i == UPDATE_IF_CHANGED && 
        !           634:                                        !(at_state.flags & AT_ST_ZT_CHANGED)) {
        !           635:                                        iocbp->ioc_count = 0;
        !           636:                                        ioc_ack(0, m, gref);
        !           637:                                        break;
        !           638:                                }
        !           639:                                mo=(gbuf_t*)NULL;
        !           640:                                tabsize = getZipTableSize();
        !           641: 
        !           642:                                        /* retrieve table into multiple gbufs */
        !           643:                                for (i =0; i<tabsize;  i+=j) {
        !           644:                                        j = tabsize - i > 
        !           645:                                                MAX_ZIP ? MAX_ZIP : tabsize - i;
        !           646:                                        size = j < MAX_ZIP ? sizeof(ZT_entry)*j : MAX_ZIP_BYTES;
        !           647:                                        if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) {
        !           648:                                                if (gbuf_cont(m))
        !           649:                                                        gbuf_freem(gbuf_cont(m));
        !           650:                                                ioc_ack(ENOBUFS, m, gref);
        !           651:                                                break;
        !           652:                                        }
        !           653:                                        if (!mo)        {               /* if first new one */
        !           654:                                                mt = mn;
        !           655:                                                total = size;
        !           656:                                        }
        !           657:                                        else {
        !           658:                                                gbuf_cont(mo) = mn;
        !           659:                                                total += size;
        !           660:                                        }
        !           661:                                        mo = mn;
        !           662:                                        getZipTable((ZT_entry*)gbuf_rptr(mn),i,j); 
        !           663:                                        gbuf_wset(mn,size);
        !           664:                                }
        !           665:                                if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) {
        !           666:                                        if (mt)
        !           667:                                                gbuf_freem(mt);
        !           668:                                        iocbp->ioc_count = 0;
        !           669:                                        ioc_ack(ENOBUFS, m, gref);
        !           670:                                        break;
        !           671:                                }
        !           672:                                if (!tabsize) {
        !           673:                                        dPrintf(D_M_ELAP,D_L_WARNING,
        !           674:                                                ("elap_wput:snmp: empty zip table\n"));
        !           675:                                        total = 0;
        !           676:                                }
        !           677:                                *(int*)gbuf_rptr(gbuf_cont(m)) = total;         /* return table size */
        !           678:                                gbuf_wset(gbuf_cont(m),sizeof(int));
        !           679:                                iocbp->ioc_count = sizeof(int);
        !           680:                                ioc_ack(0, m, gref);
        !           681:                                if (tabsize)
        !           682:                                        atalk_putnext(gref,mt);         /* send up table */
        !           683:                                at_state.flags &= ~AT_ST_ZT_CHANGED;
        !           684:                                break;
        !           685: 
        !           686:                        case LAP_IOC_SNMP_GET_RTMP:
        !           687: #ifdef APPLETALK_DEBUG
        !           688:                                kprintf("LAP_IOC_SNMP_GET_RTMP\n");
        !           689: #endif
        !           690:                                i =  *(int *)gbuf_rptr(gbuf_cont(m));
        !           691:                                gbuf_freem(gbuf_cont(m));
        !           692:                                gbuf_cont(m) = NULL;
        !           693:                                if (!(at_state.flags & AT_ST_STARTED)) {
        !           694:                                        ioc_ack(ENOTREADY, m, gref);
        !           695:                                        break;
        !           696:                                }
        !           697:                                if (i == UPDATE_IF_CHANGED && 
        !           698:                                    !(at_state.flags & AT_ST_RT_CHANGED)) {
        !           699:                                        iocbp->ioc_count = 0;
        !           700:                                        ioc_ack(0, m, gref);
        !           701:                                        break;
        !           702:                                }
        !           703: 
        !           704:                                mo=(gbuf_t*)NULL;
        !           705:                                tabsize = getRtmpTableSize();
        !           706: 
        !           707:                                        /* retrieve table into multiple gbufs */
        !           708:                                for (i =0; i<tabsize;  i+=j) {
        !           709:                                        j = tabsize - i > 
        !           710:                                                MAX_RTMP ? MAX_RTMP : tabsize - i;
        !           711:                                        size = j < MAX_RTMP ? sizeof(RT_entry)*j : MAX_RTMP_BYTES;
        !           712:                                        if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) {
        !           713:                                                if (gbuf_cont(m))
        !           714:                                                        gbuf_freem(gbuf_cont(m));
        !           715:                                                ioc_ack(ENOBUFS, m, gref);
        !           716:                                                break;
        !           717:                                        }
        !           718:                                        if (!mo)        {               /* if first new one */
        !           719:                                                mt = mn;
        !           720:                                                total = size;
        !           721:                                        }
        !           722:                                        else {
        !           723:                                                gbuf_cont(mo) = mn;
        !           724:                                                total += size;
        !           725:                                        }
        !           726:                                        mo = mn;
        !           727:                                        getRtmpTable((RT_entry*)gbuf_rptr(mn),i,j); 
        !           728:                                        gbuf_wset(mn,size);
        !           729:                                }
        !           730:                                if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) {
        !           731:                                        if (mt)
        !           732:                                                gbuf_freem(mt);
        !           733:                                        iocbp->ioc_count = 0;
        !           734:                                        ioc_ack(ENOBUFS, m, gref);
        !           735:                                        break;
        !           736:                                }
        !           737:                                if (!tabsize)
        !           738:                                        total = 0;
        !           739:                                *(int*)gbuf_rptr(gbuf_cont(m)) = total; /* return table size */
        !           740:                                gbuf_wset(gbuf_cont(m),sizeof(int));
        !           741:                                iocbp->ioc_count = sizeof(int);
        !           742:                                ioc_ack(0, m, gref);
        !           743:                                if (tabsize)
        !           744:                                        atalk_putnext(gref,mt);         /* send up table */
        !           745:                                at_state.flags &= ~AT_ST_RT_CHANGED;
        !           746:                                break;
        !           747: 
        !           748:                        case LAP_IOC_SNMP_GET_NBP:
        !           749: #ifdef APPLETALK_DEBUG
        !           750:                                kprintf("LAP_IOC_SNMP_GET_NBP\n");
        !           751: #endif
        !           752:                                i =  *(int *)gbuf_rptr(gbuf_cont(m));
        !           753:                                gbuf_freem(gbuf_cont(m));
        !           754:                                gbuf_cont(m) = NULL;
        !           755:                                if (!(at_state.flags & AT_ST_STARTED)) {
        !           756:                                        ioc_ack(ENOTREADY, m, gref);
        !           757:                                        break;
        !           758:                                }
        !           759:                                if (i == UPDATE_IF_CHANGED && 
        !           760:                                    !(at_state.flags & AT_ST_NBP_CHANGED)) {
        !           761:                                        iocbp->ioc_count = 0;
        !           762:                                        ioc_ack(0, m, gref);
        !           763:                                        dPrintf(D_M_ELAP_LOW, D_L_INFO,
        !           764:                                                ("elap_wput: nbp req denied, no change\n"));
        !           765:                                        break;
        !           766:                                }
        !           767: 
        !           768:                                mo=(gbuf_t*)NULL;
        !           769:                                tabsize = getNbpTableSize();
        !           770: 
        !           771:                                        /* retrieve table into multiple gbufs */
        !           772:                                for (i =0; i<tabsize;  i+=j) {
        !           773:                                        j = tabsize - i > 
        !           774:                                                MAX_NBP ? MAX_NBP : tabsize - i;
        !           775:                                        size = j < MAX_NBP ? sizeof(snmpNbpEntry_t)*j : MAX_NBP_BYTES;
        !           776:                                        if (!i)
        !           777:                                                size += SNMP_NBP_HEADER_SIZE;
        !           778:                                        if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) {
        !           779:                                                if (gbuf_cont(m))
        !           780:                                                        gbuf_freem(gbuf_cont(m));
        !           781:                                                ioc_ack(ENOBUFS, m, gref);
        !           782:                                                break;
        !           783:                                        }
        !           784:                                        if (!mo)        {               /* if first new one */
        !           785:                                                mt = mn;
        !           786:                                                total = size;
        !           787:                                                nbp = (snmpNbpTable_t*)gbuf_rptr(mn);
        !           788:                                                nbp->nbpt_entries = tabsize;
        !           789:                                                nbp->nbpt_zone = ifID_home->ifZoneName;
        !           790:                                                getNbpTable(nbp->nbpt_table,i,j); 
        !           791:                                        }
        !           792:                                        else {
        !           793:                                                gbuf_cont(mo) = mn;
        !           794:                                                total += size;
        !           795:                                                getNbpTable((snmpNbpEntry_t *)gbuf_rptr(mn),i,j); 
        !           796:                                        }
        !           797:                                        mo = mn;
        !           798:                                        gbuf_wset(mn,size);
        !           799:                                }
        !           800:                                if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) {
        !           801:                                        if (mt)
        !           802:                                                gbuf_freem(mt);
        !           803:                                        iocbp->ioc_count = 0;
        !           804:                                        ioc_ack(ENOBUFS, m, gref);
        !           805:                                        break;
        !           806:                                }
        !           807:                                if (!tabsize)
        !           808:                                        total = 0;
        !           809:                                *(int*)gbuf_rptr(gbuf_cont(m)) = total; /* return table size */
        !           810:                                gbuf_wset(gbuf_cont(m),sizeof(int));
        !           811:                                iocbp->ioc_count = sizeof(int);
        !           812:                                ioc_ack(0, m, gref);
        !           813:                                if (tabsize)
        !           814:                                        atalk_putnext(gref,mt);         /* send up table */
        !           815:                                at_state.flags &= ~AT_ST_NBP_CHANGED;
        !           816:                                break;
        !           817:                        }
        !           818:                                
        !           819:                        case LAP_IOC_SET_LOCAL_ZONES:
        !           820:                                {
        !           821:                                int i;
        !           822: #ifdef APPLETALK_DEBUG
        !           823:                                kprintf("LAP_IOC_SET_LOCAL_ZONES\n");
        !           824: #endif
        !           825:                                i = setLocalZones((at_nbptuple_t*)gbuf_rptr(gbuf_cont(m)),
        !           826:                                                  gbuf_len(gbuf_cont(m)));
        !           827:                                ioc_ack(i,m,gref);
        !           828:                                }
        !           829:                                break;
        !           830:                        case LAP_IOC_GET_IF_NAMES:
        !           831: #ifdef APPLETALK_DEBUG
        !           832:                                kprintf("LAP_IOC_GET_IF_NAMES\n");
        !           833: #endif
        !           834:                                if ((gbuf_cont(m) = gbuf_alloc(sizeof(if_name_t) * IF_TOTAL_MAX, 
        !           835:                                        PRI_MED)) == NULL) {
        !           836:                                        ioc_ack(ENOBUFS, m, gref);
        !           837:                                        break;
        !           838:                                }
        !           839:                                getIfNames((if_name_t *)gbuf_rptr(gbuf_cont(m)));
        !           840:                                gbuf_wset(gbuf_cont(m),sizeof(if_name_t) * IF_TOTAL_MAX);
        !           841:                                iocbp->ioc_count   = sizeof(if_name_t) * IF_TOTAL_MAX;
        !           842:                                ioc_ack(0, m, gref);
        !           843:                                break;
        !           844:                        default:
        !           845: #ifdef APPLETALK_DEBUG
        !           846:                                kprintf("unknown ioctl %d\n", iocbp->ioc_cmd);
        !           847: #endif
        !           848:                                ioc_ack(ENOTTY, m, gref);
        !           849:                                dPrintf(D_M_ELAP, D_L_WARNING,
        !           850:                                        ("elap_wput: unknown ioctl (%d)\n", iocbp->ioc_cmd));
        !           851: 
        !           852:                                if (elapp)
        !           853:                                        elapp->stats.unknown_mblks++;
        !           854:                                break;
        !           855:                        }
        !           856:                }
        !           857:                break;
        !           858: 
        !           859:        default:
        !           860:                gbuf_freem(m);
        !           861:                break;
        !           862:        }
        !           863: 
        !           864:        return 0;
        !           865: } /* elap_wput */
        !           866: 
        !           867: 
        !           868: /* Called directly by ddp/zip.
        !           869:  */
        !           870: elap_dataput(m, elapp, addr_flag, addr)
        !           871:      register  gbuf_t  *m;
        !           872:      register at_ifaddr_t *elapp;
        !           873:      u_char    addr_flag;
        !           874:      char *addr;
        !           875: {
        !           876:        register int            size;
        !           877:        int                     error;
        !           878:        extern  int             zip_type_packet();
        !           879:        struct  etalk_addr      dest_addr;
        !           880:        struct  atalk_addr      dest_at_addr;
        !           881:        extern  gbuf_t          *growmsg();
        !           882:        int                     loop = TRUE;
        !           883:                                /* flag to aarp to loopback (default) */
        !           884: 
        !           885:        /* the incoming frame is of the form {flag, address, ddp...}
        !           886:         * where "flag" indicates whether the address is an 802.3
        !           887:         * (link) address, or an appletalk address.  If it's an
        !           888:         * 802.3 address, the packet can just go out to the network
        !           889:         * through PAT, if it's an appletalk address, AT->802.3 address
        !           890:         * resolution needs to be done.
        !           891:         * If 802.3 address is known, strip off the flag and 802.3
        !           892:         * address, and prepend 802.2 and 802.3 headers.
        !           893:         */
        !           894:        
        !           895:        if (addr == NULL) {
        !           896:                addr_flag = *(u_char *)gbuf_rptr(m);
        !           897:                gbuf_rinc(m,1);
        !           898:        }
        !           899:        
        !           900:        switch (addr_flag) {
        !           901:        case AT_ADDR_NO_LOOP :
        !           902:                loop = FALSE;
        !           903:                /* pass thru */
        !           904:        case AT_ADDR :
        !           905:        if (addr == NULL) {
        !           906:            dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
        !           907:            gbuf_rinc(m,sizeof(struct atalk_addr));
        !           908:        } else
        !           909:            dest_at_addr = *(struct atalk_addr *)addr;
        !           910:            break;
        !           911:        case ET_ADDR :
        !           912:        if (addr == NULL) {
        !           913:            dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
        !           914:            gbuf_rinc(m,sizeof(struct etalk_addr));
        !           915:        } else
        !           916:            dest_addr = *(struct etalk_addr *)addr;
        !           917:            break;
        !           918:        default :
        !           919:            gbuf_freel(m);              /* unknown address type, chuck it */
        !           920:            return(EINVAL);
        !           921:         }
        !           922: 
        !           923:        m = gbuf_strip(m);
        !           924: 
        !           925:        /* At this point, rptr points to ddp header for sure */
        !           926:        if (elapp->ifState == LAP_OFFLINE) {
        !           927:            gbuf_freel(m);
        !           928:                return(ENETDOWN);
        !           929:        }
        !           930: 
        !           931:        if (elapp->ifState == LAP_ONLINE_FOR_ZIP) {
        !           932:                /* see if this is a ZIP packet that we need
        !           933:                 * to let through even though network is
        !           934:                 * not yet alive!!
        !           935:                 */
        !           936:                if (zip_type_packet(m) == 0) {
        !           937:                        gbuf_freel(m);
        !           938:                        return(ENETDOWN);
        !           939:                }
        !           940:        }
        !           941:        
        !           942:        elapp->stats.xmit_packets++;
        !           943:        size = gbuf_msgsize(m);
        !           944:        elapp->stats.xmit_bytes += size;
        !           945:        snmpStats.dd_outLong++;
        !           946:        
        !           947:        switch (addr_flag) {
        !           948:        case AT_ADDR_NO_LOOP :
        !           949:        case AT_ADDR :
        !           950:            /*
        !           951:             * we don't want elap to be looking into ddp header, so
        !           952:             * it doesn't know net#, consequently can't do 
        !           953:             * AMT_LOOKUP.  That task left to aarp now.
        !           954:             */
        !           955:            error = aarp_send_data(m,elapp,&dest_at_addr, loop);
        !           956:            break;
        !           957:        case ET_ADDR :
        !           958:            error = pat_output(elapp, m, &dest_addr, 0);
        !           959:            break;
        !           960:         }
        !           961:        return (error);
        !           962: } /* elap_dataput */
        !           963: 
        !           964: /************************************************************************
        !           965:  * elap_online()
        !           966:  *
        !           967:  ************************************************************************/
        !           968: 
        !           969: static int elap_online1(elapp)
        !           970:      at_ifaddr_t *elapp;
        !           971: {
        !           972:        int errno;
        !           973: 
        !           974:        dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online:%s elapp:0x%x\n",
        !           975:                (elapp->ifName) ? &elapp->ifName[0] : "NULL interface", (u_int) elapp));
        !           976:        if (elapp->ifState != LAP_OFFLINE)
        !           977:                return (EALREADY);
        !           978:        
        !           979:        at_state.flags |= AT_ST_IF_CHANGED;
        !           980: 
        !           981:        if (elapp->flags & ELAP_CFG_HOME) /* tell ddp_add_if if this is home */
        !           982:                elapp->ifFlags |= AT_IFF_DEFAULT;
        !           983:                
        !           984:        /* Get DDP started */
        !           985:        if ((errno = ddp_add_if(elapp)))
        !           986:                return(errno);
        !           987: 
        !           988:        /* set up multicast address for cable-wide broadcasts */
        !           989:        (void)at_reg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
        !           990: 
        !           991:        elapp->startup_inprogress = TRUE;
        !           992:        if (! (elapp->startup_error = re_aarp(elapp)))
        !           993:                (void)tsleep(&elapp->startup_inprogress, PSOCK | PCATCH, 
        !           994:                             "elap_online1", 0);
        !           995: 
        !           996:        /* then later, after some timeouts AARPwakeup() is called */
        !           997: 
        !           998:        return(elapp->startup_error);
        !           999: } /* elap_online1 */
        !          1000: 
        !          1001: static int re_aarp(elapp)
        !          1002:      at_ifaddr_t *elapp;
        !          1003: {
        !          1004:        int errno;
        !          1005: 
        !          1006:        /* We now call aarp_init() to assign an appletalk node addr */
        !          1007:        errno = aarp_init1(elapp);
        !          1008:                        /* aarp_init1() returns either -1 or ENOTREADY */
        !          1009:        if (errno == ENOTREADY)
        !          1010:                return(0);
        !          1011:        else {
        !          1012:                dPrintf(D_M_ELAP, D_L_STATE_CHG, 
        !          1013:                        ("elap_online aarp_init for %s\n", elapp->ifName));
        !          1014:                (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
        !          1015:                ddp_rem_if(elapp);
        !          1016:                elapp->ifState = LAP_OFFLINE;
        !          1017:                return(EADDRNOTAVAIL);
        !          1018:        }
        !          1019: }
        !          1020: 
        !          1021: /* called from AARPwakeup */
        !          1022: static void elap_online2(elapp)
        !          1023:      at_ifaddr_t *elapp;
        !          1024: {
        !          1025:        if (MULTIPORT_MODE) {
        !          1026:                dPrintf(D_M_ELAP,D_L_STARTUP_INFO, 
        !          1027:                        ("elap_online: re_aarp, we know it's a router...\n"));
        !          1028: 
        !          1029:                if (elapp->flags & ELAP_CFG_SEED) {
        !          1030:                        /* add route table entry (zones to be added later) */
        !          1031:                        dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
        !          1032:                                ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
        !          1033:                                elapp->ifThisCableStart, elapp->ifThisCableEnd, elapp->ifPort));
        !          1034:                        rt_insert(elapp->ifThisCableEnd,
        !          1035:                                  elapp->ifThisCableStart,
        !          1036:                                  0,0,0,
        !          1037:                                  elapp->ifPort,
        !          1038:                                  RTE_STATE_PERMANENT | RTE_STATE_ZKNOWN | RTE_STATE_GOOD
        !          1039:                                         );
        !          1040:                        /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
        !          1041:                        elapp->ifFlags |= RTR_SEED_PORT;
        !          1042:                }
        !          1043:                else 
        !          1044:                        dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
        !          1045:                                ("elap_online: it's a router, but non seed\n"));
        !          1046:        }
        !          1047: 
        !          1048:        if (elapp->flags & ELAP_CFG_ZONELESS) {
        !          1049:                /* ELAP_CFG_ZONELESS tells us that it is a router or in
        !          1050:                       multihome mode, so we don't want to do the GetNetInfo
        !          1051:                       exchange with the router.  */
        !          1052: 
        !          1053:                elapp->ifState = LAP_ONLINE_ZONELESS;
        !          1054:                elapp->startup_inprogress = FALSE;
        !          1055:                thread_wakeup(&elapp->startup_inprogress);
        !          1056:                dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 3\n"));
        !          1057:                return;
        !          1058:        }
        !          1059: 
        !          1060:        /* if we don't already have a zone and a multicast address */
        !          1061:        if (*(int *)&elapp->ZoneMcastAddr == 0 || elapp->ifZoneName.len == 0) {
        !          1062:                /* hzonehash is a global containing the nbp hash for the startup_zone */
        !          1063:                sethzonehash(elapp);
        !          1064: 
        !          1065:                /* Get ZIP rolling to get zone multicast address, etc. */
        !          1066:                elapp->ifState = LAP_ONLINE_FOR_ZIP;
        !          1067:                (void)zip_control(elapp, ZIP_ONLINE);
        !          1068:                /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
        !          1069: 
        !          1070:                /* later, after some timeouts ZIPwakeup() is called. */
        !          1071:        } else {
        !          1072:                /* otherwise, we have the zone and the multicast already,
        !          1073:                   so don't bother with another ZIP GetNetInfo request */
        !          1074:                ZIPwakeup(elapp, 0);
        !          1075:        }
        !          1076: } /* elap_online2 */
        !          1077: 
        !          1078: /* called from rtmp_router_start */
        !          1079: int elap_online3(elapp)
        !          1080:      at_ifaddr_t       *elapp;
        !          1081: {
        !          1082:        elapp->startup_inprogress = TRUE;
        !          1083: 
        !          1084:        /* just reset the net range */
        !          1085:        elapp->initial_addr.s_net = 0;
        !          1086:        elapp->initial_addr.s_node = 0;
        !          1087:        dPrintf(D_M_ELAP_LOW, D_L_STARTUP_INFO,
        !          1088:                ("elap_online: goto re_aarp port=%d\n", elapp->ifPort));
        !          1089: 
        !          1090:        if ((elapp->startup_error = re_aarp(elapp)))
        !          1091:                return(elapp->startup_error);
        !          1092: 
        !          1093:        /* then later, after some timeouts AARPwakeup() is called */
        !          1094: 
        !          1095:        (void)tsleep(&elapp->startup_inprogress, PSOCK | PCATCH, 
        !          1096:                     "elap_online3", 0);
        !          1097:        return(elapp->startup_error);
        !          1098: } /* elap_online3 */
        !          1099: 
        !          1100: /****************************************************************************
        !          1101:  * elap_offline()
        !          1102:  *
        !          1103:  ****************************************************************************/
        !          1104: 
        !          1105: void elap_offline(elapp)
        !          1106:      register at_ifaddr_t *elapp;
        !          1107: 
        !          1108: {
        !          1109:        void    zip_sched_getnetinfo(); /* forward reference */
        !          1110:        int     errno;
        !          1111:        int s;
        !          1112: 
        !          1113:        dPrintf(D_M_ELAP, D_L_SHUTDN_INFO, ("elap_offline:%s\n", elapp->ifName));
        !          1114:        if (elapp->ifState != LAP_OFFLINE) {
        !          1115: 
        !          1116:                /* Since AppleTalk is going away, remove the cable
        !          1117:                 * multicast address  and turn the interface off so that all 
        !          1118:                 * AppleTalk packets are dropped in the driver itself.
        !          1119:                 * Get rid of the zone multicast address prior to going Offline.
        !          1120:                 */
        !          1121:                (void)at_unreg_mcast(elapp, (caddr_t)&elapp->ZoneMcastAddr);
        !          1122:                (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
        !          1123:                elapp->ifState = LAP_OFFLINE;
        !          1124: 
        !          1125:                ATDISABLE(s, ddpinp_lock);
        !          1126:                if (MULTIPORT_MODE)
        !          1127:                        RT_DELETE(elapp->ifThisCableEnd,
        !          1128:                                  elapp->ifThisCableStart);
        !          1129:                ATENABLE(s, ddpinp_lock);
        !          1130: 
        !          1131:                /* make sure no zip timeouts are left running */
        !          1132:                untimeout(zip_sched_getnetinfo, elapp);
        !          1133:        }
        !          1134:        ddp_rem_if(elapp);
        !          1135: } /* elap_offline */
        !          1136: 
        !          1137: /* called only in router mode */
        !          1138: static int set_zones(ifz)
        !          1139:        if_zone_info_t *ifz;
        !          1140: 
        !          1141: /* 1. adds zone to table
        !          1142:    2. looks up each route entry from zone I/F bitmap
        !          1143:    3. sets zone bit in each route entry
        !          1144: 
        !          1145:    returns  0 if successful
        !          1146:                   -1 if error occurred
        !          1147: */
        !          1148: {
        !          1149:        int type, iftype, i;
        !          1150:        at_ifaddr_t *ifID;
        !          1151:        short zno;
        !          1152:        RT_entry *rte;
        !          1153: 
        !          1154:        zno = zt_add_zone(ifz->zone_name.str, ifz->zone_name.len);
        !          1155: 
        !          1156:        if (zno == ZT_MAXEDOUT) {
        !          1157:                dPrintf(D_M_ELAP, D_L_ERROR, ("set_zones: error: table full\n"));
        !          1158:                return(-1);
        !          1159:        }
        !          1160:        if (ifz->zone_home) {
        !          1161:                ifID_home->ifZoneName = ifz->zone_name;
        !          1162:                ifID_home->ifDefZone = zno;
        !          1163:        }
        !          1164: 
        !          1165:        for (iftype=0; iftype< IF_TYPENO_CNT; iftype++) {
        !          1166:                type = if_types[iftype].iftype;
        !          1167:                for (i=0; i<IF_TOTAL_MAX; i++)  {
        !          1168:                        if (ifz->zone_ifs[iftype] & 1<<i) {
        !          1169:                                TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1170:                                        if (ifID->aa_ifp && 
        !          1171:                                            ((ifID->aa_ifp)->if_type == type) &&
        !          1172:                                            ((ifID->aa_ifp)->if_unit == i))
        !          1173:                                                break;
        !          1174:                                }
        !          1175:                                if (ifID)  {
        !          1176:                                        rte = rt_blookup(ifID->ifThisCableEnd);
        !          1177:                                        if (!rte) {
        !          1178:                                                dPrintf(D_M_ELAP, D_L_ERROR,
        !          1179:                                                        ("set_zones: error: can't find route\n"));
        !          1180:                                        }
        !          1181:                                        zt_set_zmap(zno, rte->ZoneBitMap); 
        !          1182: 
        !          1183:                                        /* if first zone for this I/F, make default */
        !          1184:                                        if (!ifID->ifDefZone)
        !          1185:                                                 ifID->ifDefZone = zno;
        !          1186:                                }
        !          1187:                        }
        !          1188:                }
        !          1189:        }
        !          1190:        return(0);
        !          1191: }
        !          1192: 
        !          1193: static void add_route(rt)
        !          1194: RT_entry       *rt;
        !          1195: 
        !          1196: /* support ioctl to manually add routes to table. 
        !          1197:    this is really only for testing
        !          1198: */
        !          1199: {
        !          1200:        rt_insert(      rt->NetStop, rt->NetStart, rt->NextIRNet, 
        !          1201:                                rt->NextIRNode, rt->NetDist, rt->NetPort, 
        !          1202:                                rt->EntryState);
        !          1203:        dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("adding route: %ud:%ud dist:%ud\n",
        !          1204:                rt->NetStart, rt->NetStop,rt->NetDist));
        !          1205: }
        !          1206: 
        !          1207: /*
        !          1208:  * ddp_start()
        !          1209:  *
        !          1210:  * Initialization that takes place each time AppleTalk is restarted.
        !          1211:  *
        !          1212:  */
        !          1213: void ddp_start()
        !          1214: {
        !          1215:        TAILQ_INIT(&at_ifQueueHd);
        !          1216:        TAILQ_INIT(&name_registry);
        !          1217:        bzero(at_interfaces, sizeof(at_interfaces));
        !          1218:        bzero(ifID_table, sizeof(ifID_table));
        !          1219:        bzero(&at_ddp_stats, sizeof(at_ddp_stats_t));
        !          1220:        rtmp_init(); /* initialize trackedrouters */
        !          1221: 
        !          1222:        add_ddp_handler(RTMP_SOCKET, rtmp_input);
        !          1223:        ifID_home = (at_ifaddr_t *)NULL;
        !          1224:        xpatcnt = 0;
        !          1225: }
        !          1226: 
        !          1227: void ddp_shutdown()
        !          1228: {
        !          1229:        at_ifaddr_t *ifID;
        !          1230:        gref_t  *gref;
        !          1231:        int i;
        !          1232: 
        !          1233:        if (MULTIPORT_MODE) {
        !          1234:                 rtmp_shutdown();
        !          1235:                 /* free memory allocated for the rtmp/zip tables */
        !          1236:                if (ZT_table) {
        !          1237:                        FREE(ZT_table, M_RTABLE);
        !          1238:                        ZT_table = (ZT_entry *)NULL;
        !          1239:                }
        !          1240:                if (RT_table) {
        !          1241:                        FREE(RT_table, M_RTABLE);
        !          1242:                        RT_table = (RT_entry *)NULL;
        !          1243:                }
        !          1244:        }          
        !          1245: 
        !          1246:        at_state.flags = 0;     /* make sure inits are done on restart */
        !          1247: 
        !          1248:        /* from original ddp_shutdown() */
        !          1249:        nbp_shutdown();         /* clear all known NVE */
        !          1250:        routershutdown();
        !          1251:        ddp_brt_shutdown();
        !          1252: 
        !          1253:        /* Network is shutting down... send error messages up on each open
        !          1254:         * socket.  From ddps_shutdown().
        !          1255:         */
        !          1256:        for (gref = ddp_head.atpcb_next; gref != &ddp_head; gref = gref->atpcb_next)
        !          1257:                atalk_notify(gref, ESHUTDOWN);
        !          1258: 
        !          1259:        if (adspInited) {
        !          1260:                CleanupGlobals();
        !          1261:                adspInited = 0;
        !          1262:        }
        !          1263:        dPrintf(D_M_DDP, D_L_VERBOSE, ("DDP shutdown completed"));
        !          1264:          
        !          1265:        /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
        !          1266:               this is the only place to find the ifID *** */
        !          1267:        for (i = 0; i < IF_TOTAL_MAX; i++) {
        !          1268:                ifID = &at_interfaces[i];
        !          1269:                /* do LAP_IOC_OFFLINE processing */
        !          1270:                elap_offline(ifID);
        !          1271:        }
        !          1272:        ddp_start();
        !          1273: } /* ddp_shutdown */
        !          1274: 
        !          1275: int routerStart(keP)
        !          1276:      at_kern_err_t *keP;
        !          1277: {
        !          1278:        register at_ifaddr_t *ifID;
        !          1279:        int error;
        !          1280: 
        !          1281:        if (! ifID_home)
        !          1282:                return(EINVAL);
        !          1283: 
        !          1284:        /*
        !          1285:         * this will cause the ports to glean from the net the relevant
        !          1286:         * information before forwarding
        !          1287:         */
        !          1288:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1289:                dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 
        !          1290:                        ("routerStart Port %d (%s) set to activating\n",
        !          1291:                         ifID->ifPort, ifID->ifName));
        !          1292:                ifID->ifRoutingState = PORT_ACTIVATING;
        !          1293:                ifID->ifFlags |= RTR_XNET_PORT;
        !          1294:        }
        !          1295: 
        !          1296:        /*
        !          1297:         * The next step is to check the information for each port before
        !          1298:         * declaring the ports up and forwarding
        !          1299:         */
        !          1300:        dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
        !          1301:                ("router_start: waiting 20 sec before starting up\n"));
        !          1302: 
        !          1303:        /* sleep for 20 seconds */
        !          1304:        if ((error = 
        !          1305:             /* *** eventually this will be the ifID for the interface
        !          1306:                being brought up in router mode *** */
        !          1307:             tsleep(&ifID_home->startup_inprogress, 
        !          1308:                    PSOCK | PCATCH, "routerStart", 20 * SYS_HZ))
        !          1309:            != EWOULDBLOCK) {
        !          1310: /*
        !          1311:                if (!error)
        !          1312:                        panic("routerStart: spurious interrupt");
        !          1313: */
        !          1314:                return(error);
        !          1315:        }
        !          1316: 
        !          1317:        return(rtmp_router_start(keP));
        !          1318:        /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ);  */
        !          1319: } /* routerStart */
        !          1320: 
        !          1321: void ZIPwakeup(elapp, ZipError)
        !          1322:      at_ifaddr_t *elapp;
        !          1323:      int ZipError;
        !          1324: {
        !          1325:        int s, error = ZipError;
        !          1326: 
        !          1327:        ATDISABLE(s, ddpinp_lock);
        !          1328:        if ( (elapp != NULL) && elapp->startup_inprogress) {
        !          1329:                ATENABLE(s, ddpinp_lock);
        !          1330: 
        !          1331:                /* was ZIPContinue */
        !          1332:                /* was elapp_online() with jump to ZIP_sleep */
        !          1333: 
        !          1334:                /* instead of the goto ZIP_sleep ... */
        !          1335:                switch (ZipError) {
        !          1336:                        case 0 : /* success */
        !          1337:                            elapp->ifState = LAP_ONLINE;
        !          1338:                            break;
        !          1339:                        case ZIP_RE_AARP :
        !          1340:                            /* instead of goto re_aarp; */
        !          1341:                            /* We now call aarp_init() to assign an 
        !          1342:                               appletalk node addr */
        !          1343:                            if ((elapp->startup_error = re_aarp(elapp))) {
        !          1344:                                elapp->startup_inprogress = FALSE;
        !          1345:                                thread_wakeup(&elapp->startup_inprogress);
        !          1346:                                dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 
        !          1347:                                        ("elap_online: ack 2\n"));
        !          1348:                            }
        !          1349:                            break;
        !          1350:                        default :
        !          1351:                            break;
        !          1352:                }
        !          1353:                if (ZipError != ZIP_RE_AARP) {
        !          1354:                        elapp->startup_error = error;
        !          1355:                        elapp->startup_inprogress = FALSE;
        !          1356:                        thread_wakeup(&elapp->startup_inprogress);
        !          1357:                        dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
        !          1358:                                ("elap_online: ifZipError=%d\n", error));
        !          1359:                }
        !          1360:        } else
        !          1361:                ATENABLE(s, ddpinp_lock);
        !          1362: } /* ZIPwakeup */
        !          1363: 
        !          1364: void AARPwakeup(probe_cb)
        !          1365:      aarp_amt_t *probe_cb;
        !          1366: {
        !          1367:        int s;
        !          1368:        int errno;
        !          1369:        at_ifaddr_t *elapp;
        !          1370: 
        !          1371:        ATDISABLE(s, arpinp_lock);
        !          1372:        elapp = probe_cb->elapp;
        !          1373:        if ( (elapp != NULL) && elapp->startup_inprogress ) {
        !          1374:                ATENABLE(s, arpinp_lock);
        !          1375: 
        !          1376:                /* was AARPContinue */
        !          1377:                errno = aarp_init2(elapp);
        !          1378:                /* aarp_init2() returns either -1 or 0 */
        !          1379:                if (errno != 0) {
        !          1380:                        dPrintf(D_M_ELAP, D_L_STATE_CHG, 
        !          1381:                                ("elap_online aarp_init for %s\n",
        !          1382:                                 elapp->ifName));
        !          1383:                        (void)at_unreg_mcast(elapp, (caddr_t)&elapp->ZoneMcastAddr);
        !          1384:                        (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
        !          1385:                        elapp->ifState = LAP_OFFLINE;
        !          1386:                        ddp_rem_if(elapp);
        !          1387:                        elapp->startup_error = EADDRNOTAVAIL;
        !          1388:                        elapp->startup_inprogress = FALSE;
        !          1389:                        thread_wakeup(&elapp->startup_inprogress);
        !          1390:                        dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 2\n"));
        !          1391:                } else {
        !          1392:                        dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
        !          1393:                                ("elap_online: aarp_init returns zero\n"));
        !          1394:                        elap_online2(elapp);
        !          1395:                }
        !          1396:        } else
        !          1397:                ATENABLE(s, arpinp_lock);
        !          1398: } /* AARPwakeup */
        !          1399: 
        !          1400: static void getIfNames(names)
        !          1401:      if_name_t *names;
        !          1402: {
        !          1403:        int i;
        !          1404:        at_ifaddr_t *ifID;
        !          1405:        bzero(names,sizeof(if_name_t) * IF_TOTAL_MAX);
        !          1406:        for (i=0, ifID=ifID_table[0]; ifID; ifID = ifID_table[++i], names++)
        !          1407:                if(ifID)
        !          1408:                        strncpy((char *)names,ifID->ifName,sizeof(*names));
        !          1409: 
        !          1410:        return;
        !          1411: }
        !          1412: 
        !          1413: void ddp_bit_reverse(addr)
        !          1414:        unsigned char *addr;
        !          1415: {
        !          1416: static unsigned char reverse_data[] = {
        !          1417:        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
        !          1418:        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
        !          1419:        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
        !          1420:        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
        !          1421:        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
        !          1422:        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
        !          1423:        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
        !          1424:        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
        !          1425:        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
        !          1426:        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
        !          1427:        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
        !          1428:        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
        !          1429:        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
        !          1430:        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
        !          1431:        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
        !          1432:        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
        !          1433:        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
        !          1434:        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
        !          1435:        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
        !          1436:        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
        !          1437:        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
        !          1438:        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
        !          1439:        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
        !          1440:        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
        !          1441:        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
        !          1442:        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
        !          1443:        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
        !          1444:        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
        !          1445:        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
        !          1446:        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
        !          1447:        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
        !          1448:        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
        !          1449:        };
        !          1450: 
        !          1451:        unsigned char k;
        !          1452: 
        !          1453:        for (k=0; k < 6; k++)
        !          1454:                addr[k] = reverse_data[addr[k]];
        !          1455: }
        !          1456: 
        !          1457: static int elap_trackMcast(patp, func, addr)
        !          1458:        at_ifaddr_t    *patp;
        !          1459:        int func;
        !          1460:        caddr_t addr;
        !          1461: {
        !          1462:        int i, loc=-1;
        !          1463:        u_char c;
        !          1464:        switch(patp->aa_ifp->if_type) {
        !          1465:        case IFT_ETHER: 
        !          1466:        case IFT_FDDI: 
        !          1467:                /* set addr to point to unique part of addr */
        !          1468:                c = addr[5];
        !          1469: 
        !          1470:                /* first try to find match */
        !          1471:                /* *** save just one byte of the multicast address? *** */
        !          1472:                for (i=0; i< MAX_MCASTS; i++) 
        !          1473:                        if (c == patp->mcast[i]) {
        !          1474:                                loc = i;
        !          1475:                                break;
        !          1476:                        }
        !          1477:                                
        !          1478:                switch (func) {
        !          1479:                case MCAST_TRACK_DELETE:
        !          1480:                        if (loc >= 0) 
        !          1481:                                patp->mcast[loc] = 0;
        !          1482: 
        !          1483:                        break;
        !          1484:                case MCAST_TRACK_ADD:
        !          1485:                        dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add loc:%d\n", i));
        !          1486:                        if (loc >= 0) {
        !          1487:                                dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was there\n"));
        !          1488:                                return(1);
        !          1489:                                break;                  /* already there */
        !          1490:                        }               
        !          1491:                        for (i=0; i< MAX_MCASTS; i++) 
        !          1492:                                if (patp->mcast[i] == 0) {
        !          1493:                                        loc = i;
        !          1494:                                        break;
        !          1495:                                }
        !          1496:                        dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add1 loc:%d\n", i));
        !          1497:                        if (loc >= 0) {
        !          1498:                                patp->mcast[loc] = c;
        !          1499:                                dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, adding(%x)\n",
        !          1500:                                        (*(int*)addr)&0xffffff));
        !          1501:                        }
        !          1502:                        else {
        !          1503:                                /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
        !          1504:                                return(-1);
        !          1505:                        }
        !          1506:                        break;  
        !          1507:                case MCAST_TRACK_CHECK:
        !          1508:                        if (loc >= 0) {
        !          1509:                                dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:check, addr was there\n"));
        !          1510:                                return(0);
        !          1511:                        }
        !          1512:                        else {
        !          1513:                                dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was NOT there\n"));
        !          1514:                                return(-1);
        !          1515:                        }
        !          1516:                        
        !          1517:                default:
        !          1518:                        /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
        !          1519:                        return(-1);
        !          1520:                }
        !          1521: 
        !          1522:        case IFT_ISO88025: /* token ring */
        !          1523:                /* we would use the lowest byte of the addr argument as a value
        !          1524:                   to shift left a 1 to form the mcast mask for TR. We'll do this
        !          1525:                   when the time comes
        !          1526:                 */
        !          1527:        default:
        !          1528:                ;
        !          1529:        }
        !          1530:        return(0);
        !          1531: }
        !          1532: 
        !          1533: 
        !          1534: static getSnmpCfg(snmp)
        !          1535:        snmpCfg_t *snmp;
        !          1536: {
        !          1537:        int i;
        !          1538:        at_ifaddr_t     *elapp;
        !          1539:        snmpIfCfg_t     *ifc;
        !          1540: 
        !          1541:        snmp->cfg_ifCnt = 0;
        !          1542:        
        !          1543:        bzero(snmp,sizeof(snmpCfg_t));
        !          1544:        for (i=0, elapp=at_interfaces,ifc=snmp->cfg_ifCfg; 
        !          1545:                 i<IF_TOTAL_MAX; i++, elapp++, ifc++) {
        !          1546:                if (elapp->ifState != LAP_OFFLINE) {
        !          1547:                        snmp->cfg_ifCnt++;
        !          1548:                        strncpy(ifc->ifc_name,elapp->ifName, sizeof(ifc->ifc_name));
        !          1549:                        ifc->ifc_aarpSize = getAarpTableSize(i);
        !          1550:                        ifc->ifc_addrSize = getPhysAddrSize(i);
        !          1551:                        switch (elapp->aa_ifp->if_type) {
        !          1552:                                case IFT_ETHER:
        !          1553:                                        ifc->ifc_type = SNMP_TYPE_ETHER2;
        !          1554:                                        break;
        !          1555:                                case IFT_ISO88025: /* token ring */
        !          1556:                                        ifc->ifc_type = SNMP_TYPE_TOKEN;
        !          1557:                                        break;
        !          1558:                                case IFT_FDDI:
        !          1559:                                default:
        !          1560:                                        ifc->ifc_type = SNMP_TYPE_OTHER;
        !          1561:                                        break;
        !          1562:                        }
        !          1563:                        ifc->ifc_start  = elapp->ifThisCableStart;
        !          1564:                        ifc->ifc_end    = elapp->ifThisCableEnd;
        !          1565:                        ifc->ifc_ddpAddr= elapp->ifThisNode;
        !          1566:                        ifc->ifc_status = elapp->ifState == LAP_ONLINE ? 1 : 2;
        !          1567:                        ifc->ifc_zoneName.len = 0;
        !          1568:                        if (elapp->ifZoneName.len != 0) {
        !          1569:                                ifc->ifc_zoneName = elapp->ifZoneName;
        !          1570:                        }
        !          1571:                        else if (elapp->ifDefZone) {
        !          1572:                                ifc->ifc_zoneName = ZT_table[elapp->ifDefZone-1].Zone;
        !          1573:                        }
        !          1574:                        else    /* temp, debug only */
        !          1575:                                ifc->ifc_zoneName = ZT_table[0].Zone;
        !          1576:                        if (ROUTING_MODE) {
        !          1577:                                if (elapp->ifFlags & RTR_SEED_PORT) {
        !          1578:                                        ifc->ifc_netCfg  = SNMP_CFG_CONFIGURED;
        !          1579:                                        ifc->ifc_zoneCfg = SNMP_CFG_CONFIGURED;
        !          1580:                                }
        !          1581:                                else {
        !          1582:                                        ifc->ifc_netCfg  = SNMP_CFG_GARNERED;
        !          1583:                                        ifc->ifc_zoneCfg = SNMP_CFG_GARNERED;
        !          1584:                                }
        !          1585:                        }
        !          1586:                        else  {         /* single-port mode */
        !          1587:                                if (elapp->ifRouterState == ROUTER_AROUND) {
        !          1588:                                        ifc->ifc_netCfg = SNMP_CFG_GARNERED;
        !          1589:                                }
        !          1590:                                else {
        !          1591:                                        ifc->ifc_netCfg = SNMP_CFG_GUESSED;
        !          1592:                                        ifc->ifc_zoneCfg = SNMP_CFG_UNCONFIG;
        !          1593:                                }
        !          1594:                        }
        !          1595:                }
        !          1596:        } 
        !          1597:        snmp->cfg_flags = at_state.flags;
        !          1598: 
        !          1599:                
        !          1600:        return(0);
        !          1601: }      
        !          1602: 
        !          1603: int at_reg_mcast(ifID, data)
        !          1604:      at_ifaddr_t *ifID;
        !          1605:      caddr_t data;
        !          1606: {
        !          1607:        struct ifnet *nddp = ifID->aa_ifp;
        !          1608:        struct ifreq request;
        !          1609: 
        !          1610:        if (!nddp) {
        !          1611:                dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
        !          1612:                return(-1);
        !          1613:        }
        !          1614:        if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1)
        !          1615:                return(0);
        !          1616: 
        !          1617:        /* this is for ether_output */
        !          1618:        request.ifr_addr.sa_family = AF_UNSPEC;
        !          1619:        request.ifr_addr.sa_len = 2 + sizeof(struct etalk_addr);
        !          1620:        bcopy (data, &request.ifr_addr.sa_data[0], sizeof(struct etalk_addr));
        !          1621: 
        !          1622:        /*### LD Direct access to the ifp->if_ioctl function */
        !          1623: 
        !          1624:        dPrintf(D_M_PAT, D_L_STARTUP,
        !          1625:                ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
        !          1626:                 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 
        !          1627:                 (unsigned)ifID));
        !          1628: 
        !          1629: /*
        !          1630:        if ((*nddp->if_ioctl)(nddp, SIOCADDMULTI, (caddr_t)&request))
        !          1631:                return(-1);
        !          1632: */
        !          1633:        if (if_addmulti(nddp, &request.ifr_addr, 0))
        !          1634:            return -1;
        !          1635:        else
        !          1636:            return 0;
        !          1637: 
        !          1638: }
        !          1639: 
        !          1640: int at_unreg_mcast(ifID, data)
        !          1641:      at_ifaddr_t *ifID;
        !          1642:      caddr_t data;
        !          1643: {
        !          1644:        struct ifnet *nddp = ifID->aa_ifp;
        !          1645:        struct ifreq request;
        !          1646: 
        !          1647: 
        !          1648:        if (*(int *)data) {
        !          1649:                if (!nddp) {
        !          1650:                        dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
        !          1651:                        return(-1);
        !          1652:                }
        !          1653: 
        !          1654:                elap_trackMcast(ifID, MCAST_TRACK_DELETE, data);
        !          1655: 
        !          1656:                /* this is for ether_output */
        !          1657:                request.ifr_addr.sa_family = AF_UNSPEC;
        !          1658:                request.ifr_addr.sa_len = 2 + sizeof(struct etalk_addr);
        !          1659:                bcopy (data, &request.ifr_addr.sa_data[0], sizeof(struct etalk_addr));
        !          1660: 
        !          1661:                /*### LD Direct access to the ifp->if_ioctl function */
        !          1662:                dPrintf(D_M_PAT, D_L_STARTUP,
        !          1663:                        ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
        !          1664:                         *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 
        !          1665:                         (unsigned)ifID));
        !          1666: /*
        !          1667:                if ((*nddp->if_ioctl)(nddp, SIOCDELMULTI, (caddr_t)&request))
        !          1668:                        return(-1);
        !          1669: */
        !          1670:                bzero(data, sizeof(struct etalk_addr));
        !          1671:        }
        !          1672: 
        !          1673:        if (if_delmulti(nddp, &request.ifr_addr))
        !          1674:            return -1;
        !          1675:        else
        !          1676:            return 0;
        !          1677: }
        !          1678: #ifdef NOT_YET
        !          1679: /* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
        !          1680:        new code to allow an AF_LINK address family multicast to be (un)registered
        !          1681:        using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
        !          1682: 
        !          1683:        The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not 
        !          1684:        fit in the "struct ifreq" that is used for these ioctls, and we do not want
        !          1685:        Blue/Classic, which currently uses AF_UNSPEC, to use a different address 
        !          1686:        family multicast address than Mac OS X uses.
        !          1687:    *** */
        !          1688: 
        !          1689: int at_reg_mcast(ifID, data)
        !          1690:      at_ifaddr_t *ifID;
        !          1691:      caddr_t data;
        !          1692: {
        !          1693:        struct ifnet *nddp = ifID->aa_ifp;
        !          1694:        struct sockaddr_dl sdl;
        !          1695: 
        !          1696:        if (*(int *)data) {
        !          1697:                if (!nddp) {
        !          1698:                        dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
        !          1699:                        return(-1);
        !          1700:                }
        !          1701:                if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1)
        !          1702:                        return(0);
        !          1703: 
        !          1704:                sdl.sdl_len = sizeof(struct sockaddr_dl);
        !          1705:                sdl.sdl_family = AF_LINK;
        !          1706:                sdl.sdl_index = 0;
        !          1707:                sdl.sdl_type = nddp->if_type;
        !          1708:                sdl.sdl_alen = nddp->if_addrlen;
        !          1709:                sdl.sdl_slen = 0;
        !          1710:                sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d", 
        !          1711:                                       nddp->if_name , nddp->if_unit);
        !          1712:                bcopy(data, LLADDR(&sdl), sdl.sdl_alen);
        !          1713: 
        !          1714:                dPrintf(D_M_PAT, D_L_STARTUP,
        !          1715:                        ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
        !          1716:                         *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 
        !          1717:                         (unsigned)ifID));
        !          1718: 
        !          1719:                if (if_addmulti(nddp, (struct sockaddr *)&sdl, 0))
        !          1720:                        return -1;
        !          1721:        }
        !          1722: 
        !          1723:        return 0;
        !          1724: }
        !          1725: 
        !          1726: int at_unreg_mcast(ifID, data)
        !          1727:      at_ifaddr_t *ifID;
        !          1728:      caddr_t data;
        !          1729: {
        !          1730:        struct ifnet *nddp = ifID->aa_ifp;
        !          1731:        struct sockaddr_dl sdl;
        !          1732: 
        !          1733:        if (*(int *)data) {
        !          1734:                if (!nddp) {
        !          1735:                        dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
        !          1736:                        return(-1);
        !          1737:                }
        !          1738: 
        !          1739:                elap_trackMcast(ifID, MCAST_TRACK_DELETE, data);
        !          1740: 
        !          1741:                sdl.sdl_len = sizeof(struct sockaddr_dl);
        !          1742:                sdl.sdl_family = AF_LINK;
        !          1743:                sdl.sdl_index = 0;
        !          1744:                sdl.sdl_type = nddp->if_type;
        !          1745:                sdl.sdl_alen = nddp->if_addrlen;
        !          1746:                sdl.sdl_slen = 0;
        !          1747:                sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d", 
        !          1748:                                       nddp->if_name , nddp->if_unit);
        !          1749: 
        !          1750:                dPrintf(D_M_PAT, D_L_STARTUP,
        !          1751:                        ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
        !          1752:                         *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 
        !          1753:                         (unsigned)ifID));
        !          1754:                bzero(data, ETHERNET_ADDR_LEN); 
        !          1755: 
        !          1756:                if (if_delmulti(nddp, (struct sockaddr *)&sdl))
        !          1757:                        return(-1);
        !          1758:        }
        !          1759: 
        !          1760:        return 0;
        !          1761: }
        !          1762: 
        !          1763: #endif

unix.superglobalmegacorp.com

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