Annotation of XNU/bsd/netat/ddp_nbp.c, revision 1.1.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, 1997, 1998 Apple Computer, Inc. 
                     24:  *
                     25:  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
                     26:  */
                     27: 
                     28: #include <string.h>
                     29: 
                     30: #include <sys/errno.h>
                     31: #include <sys/types.h>
                     32: #include <sys/param.h>
                     33: #include <machine/spl.h>
                     34: #include <sys/systm.h>
                     35: #include <sys/kernel.h>
                     36: #include <sys/proc.h>
                     37: #include <sys/filedesc.h>
                     38: #include <sys/fcntl.h>
                     39: #include <sys/mbuf.h>
                     40: #include <sys/ioctl.h>
                     41: #include <sys/malloc.h>
                     42: #include <sys/socket.h>
                     43: #include <sys/socketvar.h>
                     44: 
                     45: #include <net/if.h>
                     46: #include <net/if_types.h>
                     47: 
                     48: #include <netat/sysglue.h>
                     49: #include <netat/appletalk.h>
                     50: #include <netat/at_var.h>
                     51: #include <netat/ddp.h>
                     52: #include <netat/nbp.h>
                     53: #include <netat/zip.h>
                     54: #include <netat/rtmp.h>
                     55: #include <netat/lap.h>
                     56: #include <netat/routing_tables.h>      /* router */
                     57: #include <netat/at_snmp.h>
                     58: #include <netat/at_pcb.h>
                     59: #include <netat/debug.h>
                     60: #include <netat/at_config.h>
                     61: 
                     62: /* reaching for DDP and NBP headers in the datagram */
                     63: #define DATA_DDP(mp)   ((at_ddp_t *)(gbuf_rptr(mp)))
                     64: #define        DATA_NBP(mp)    ((at_nbp_t *)((DATA_DDP(mp))->data))
                     65: 
                     66: /* Get to the nve_entry_t part ofthe buffer */
                     67: #define        NVE_ENTRY(mp)   (nve_entry_t *)(gbuf_rptr(mp))
                     68: 
                     69: #ifndef        MIN
                     70: #define        MIN(a,b)        ((a)>(b)?(b):(a))
                     71: #endif
                     72: 
                     73: #define        errno   nbperrno
                     74: #define NBP_DEBUG  0
                     75: 
                     76:        /* externs */
                     77: extern at_ifaddr_t *ifID_table[];
                     78: extern at_ifaddr_t *ifID_home;
                     79: 
                     80: TAILQ_HEAD(name_registry, _nve_) name_registry;
                     81: 
                     82: atlock_t       nve_lock;
                     83: 
                     84: /* statics */
                     85: static int             errno;
                     86: static  gbuf_t  *lzones=0;     /* head of local zones list */
                     87: static int     lzonecnt=0;             /* # zones stored in lzones     */
                     88: static u_int  hzonehash=0;     /* hash val of home zone */
                     89: static int     nve_lock_pri;
                     90: 
                     91: static int     nbp_lkup_reply(nbp_req_t *, nve_entry_t *);
                     92: static int     nbp_strcmp(at_nvestr_t *, at_nvestr_t *, u_char);
                     93: static int     nbp_setup_resp(nbp_req_t *, int);
                     94: static int     nbp_send_resp(nbp_req_t *);
                     95: static int     nbp_validate_n_hash(nbp_req_t *, int, int);
                     96: static nve_entry_t     *nbp_search_nve();
                     97: static int isZoneLocal(at_nvestr_t *);
                     98: 
                     99: /* macros */
                    100: #define NVE_LOCK nve_lock
                    101: 
                    102: /* prototypes */
                    103: void nbp_delete_entry();
                    104: extern int at_reg_mcast();
                    105: extern at_nvestr_t *getRTRLocalZone(if_zone_t *);
                    106: extern void    nbp_add_multicast( at_nvestr_t *, at_ifaddr_t *);
                    107: 
                    108: static long nbp_id_count = 0;
                    109: 
                    110: void sethzonehash(elapp)
                    111:      at_ifaddr_t *elapp;
                    112: {
                    113:        if (elapp->startup_zone.len)  {
                    114:                hzonehash = nbp_strhash(&elapp->startup_zone);
                    115:        }
                    116: }
                    117: 
                    118: void nbp_shutdown()
                    119: {
                    120:        /* delete all NVE's and release buffers */
                    121:        register nve_entry_t    *nve_entry, *next_nve;
                    122: 
                    123:        ATDISABLE(nve_lock_pri,NVE_LOCK);
                    124:        TAILQ_FOREACH(nve_entry, &name_registry, nve_link) {
                    125:                nbp_delete_entry(nve_entry);
                    126:        }
                    127:        ATENABLE(nve_lock_pri,NVE_LOCK);
                    128: 
                    129:        if (lzones) {
                    130:                gbuf_freem(lzones);
                    131:                lzonecnt = 0;
                    132:                lzones = NULL; 
                    133:        }
                    134: } /* nbp_shutdown */
                    135: 
                    136: static
                    137: u_char *nbp2zone(nbp, maxp)
                    138:        at_nbp_t *nbp;
                    139:        u_char *maxp;
                    140: {
                    141: 
                    142:        u_char *p;
                    143: 
                    144:        p = (u_char*)&nbp->tuple[0].enu_entity; /* p -> object */
                    145:        if (p >= maxp) return NULL;
                    146:        p += (*p +1);                           /* p -> type   */
                    147:        if (p >= maxp) return NULL;
                    148:        p += (*p +1);                           /* p -> zone   */
                    149:        if (p >= maxp) return NULL;
                    150:        if ((p + *p) >= maxp) return NULL;
                    151:        return(p);
                    152: }
                    153: 
                    154: void nbp_input(m, ifID)
                    155:      register gbuf_t   *m;
                    156:      register at_ifaddr_t *ifID;
                    157: 
                    158: {
                    159:        register at_ddp_t       *ddp = DATA_DDP(m);
                    160:        register at_nbp_t       *nbp = DATA_NBP(m);
                    161:        register nve_entry_t    *nve_entry, *next_nve;
                    162:        register RT_entry       *rt;
                    163:        register int ddpSent = FALSE;   /* true if we re-sent this pkt (don't free) */
                    164:        struct etalk_addr mcastAddr;
                    165:        nbp_req_t       nbp_req;
                    166:        u_char *p;
                    167:        
                    168:        /* from original nbp_input() when this function was nbp_handler() */
                    169:        if ((gbuf_type(m) != MT_DATA && gbuf_type(m) != MSG_DATA) ||
                    170:            ddp->type != DDP_NBP) {
                    171:                gbuf_freem(m);      
                    172:                return;
                    173:        }
                    174: 
                    175:        /* Some initializations */
                    176:        nbp_req.response = NULL;
                    177:        nbp_req.request = m;
                    178:        nbp_req.space_unused = nbp_req.flags = 0;
                    179: 
                    180:        dPrintf(D_M_NBP_LOW, D_L_USR1,
                    181:                ("nbp_input control:%d tuplecount:%d id:%d\n",
                    182:                nbp->control, nbp->tuple_count, nbp->at_nbp_id));
                    183:        switch (nbp->control) {
                    184:        case NBP_LKUP :
                    185:          {
                    186:                at_net_al dst_net;
                    187: 
                    188:                dst_net = NET_VALUE(ddp->dst_net);
                    189:                dPrintf(D_M_NBP_LOW, D_L_USR2, (" LKUP %s\n",
                    190:                        ifID != ifID_home ? "non-home" : "home"));
                    191:                if ( ROUTING_MODE && (NET_VALUE(ddp->dst_net) != 0)
                    192:                        && ((dst_net < ifID->ifThisCableStart)
                    193:                            || (dst_net > ifID->ifThisCableEnd)) ) {
                    194:                        routing_needed(m, ifID, TRUE);
                    195:                        ddpSent = TRUE;
                    196:                        break;
                    197:                }
                    198:          }
                    199: 
                    200:                if (nbp_validate_n_hash (&nbp_req, TRUE, FALSE) == 0) {
                    201:                        nbp_req.func = nbp_lkup_reply;
                    202:                        (void) nbp_search_nve(&nbp_req, ifID);
                    203:                        if (nbp_req.response) {
                    204:                                nbp_send_resp(&nbp_req);
                    205:                        }
                    206:                }
                    207: #ifdef NBP_DEBUG
                    208:        {
                    209:                char zone[35],object[35],type[35];
                    210:                strncpy(zone,nbp_req.nve.zone.str, nbp_req.nve.zone.len);
                    211:                strncpy(object,nbp_req.nve.object.str, nbp_req.nve.object.len);
                    212:                strncpy(type,nbp_req.nve.type.str, nbp_req.nve.type.len);
                    213:                object[nbp_req.nve.object.len] = '\0';
                    214:                zone[nbp_req.nve.zone.len] = '\0';
                    215:                type[nbp_req.nve.type.len] = '\0';
                    216:                if (ifID != ifID_home) 
                    217:                        dPrintf(D_M_NBP_LOW,D_L_USR2,
                    218:                                ("nbp_LKUP for:%s:%s@%s", object, type, zone));
                    219:        }
                    220: #endif /* NBP_DEBUG */
                    221: 
                    222:                break;
                    223:        case NBP_FWDRQ: 
                    224:                {
                    225:                register int    zhome=0;
                    226:                                /* true if home zone == destination zone */
                    227:                register int    zno, i;
                    228:                register  gbuf_t        *m2;
                    229:                register error_found =0;
                    230:                register at_ifaddr_t *ifIDorig;
                    231: 
                    232:                if (!ROUTING_MODE)      /* for routers only! */
                    233:                        break;
                    234: 
                    235:                ifIDorig = ifID;
                    236:                ifID= NULL;
                    237:                for (i = 0 ; i < RT_maxentry; i++) {
                    238:                        rt = &RT_table[i];
                    239:                        if ((rt->EntryState & RTE_STATE_PERMANENT) &&
                    240:                                NET_VALUE(ddp->dst_net) >= rt->NetStart && 
                    241:                                NET_VALUE(ddp->dst_net) <=      rt->NetStop
                    242:                           ) {
                    243:                                /* sanity check */
                    244:                                if (rt->NetPort >= IF_TOTAL_MAX) {
                    245:                                        dPrintf(D_M_NBP,D_L_ERROR,
                    246:                                                ("nbp_input:FWDREQ: bad port# from RT_table\n"));
                    247:                                        error_found = TRUE;
                    248:                                        break;
                    249:                                }
                    250:                                ifID = ifID_table[rt->NetPort];
                    251:                                if (!ifID) {
                    252:                                        dPrintf(D_M_NBP,D_L_ERROR,
                    253:                                                ("nbp_input:FWDREQ: ifID %s\n", 
                    254:                                                !ifID ? "not found" : "invalid"));
                    255:                                        error_found = TRUE;
                    256:                                        break;
                    257:                                }
                    258:                                if (ifID->ifState == LAP_OFFLINE) {
                    259:                                        dPrintf(D_M_NBP,D_L_ERROR,
                    260:                                                ("nbp_input:FWDREQ: ifID offline (port %d)\n",
                    261:                                                rt->NetPort));
                    262:                                        error_found = TRUE;
                    263:                                        break;
                    264:                                }
                    265:                           break;
                    266:                        }
                    267:                }
                    268:                if (error_found) /* the port is not correct */
                    269:                        break;
                    270: 
                    271:                if (!ifID) { /* this packet is not for us, let the routing engine handle it  */
                    272:                        routing_needed(m, ifIDorig, TRUE);
                    273:                        ddpSent= TRUE;
                    274:                        break;
                    275:                }
                    276: 
                    277:                /* 
                    278:                 * At this point, we have a valid Forward request for one of our 
                    279:                 * directly connected port. Convert it to a NBP Lookup
                    280:                 */
                    281: 
                    282:                nbp->control = NBP_LKUP;
                    283:                NET_ASSIGN(ddp->dst_net, 0);
                    284:                ddp->dst_node = 255;
                    285: 
                    286: 
                    287:  /*### LD 01/18/94 Check if the dest is also the home zone. */
                    288:  
                    289:                p = nbp2zone(nbp, gbuf_wptr(m));
                    290:                if ((p == NULL) || !(zno = zt_find_zname(p))) {
                    291:                        dPrintf(D_M_NBP,D_L_WARNING,
                    292:                                ("nbp_input: FWDRQ:zone not found\n"));
                    293:                        break;
                    294:                }
                    295:                if (isZoneLocal((at_nvestr_t*)p)) 
                    296:                        zhome = TRUE;                           /* one of our  ports is in destination zone */
                    297:                if (!zt_get_zmcast(ifID, p, &mcastAddr)) {
                    298:                        dPrintf(D_M_NBP,D_L_ERROR,
                    299:                                ("nbp_input: FDWREQ:zt_get_zmcast error\n"));
                    300:                        break;
                    301:                }
                    302:                        
                    303: 
                    304:                if (zhome) { /*### LD 01/18/95  In case our home is here, call back nbp */
                    305:  
                    306:                        if (!(m2 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) {
                    307:                                dPrintf(D_M_NBP,D_L_ERROR, 
                    308:                                        ("nbp_input: FWDRQ:gbuf_copym failed\n"));
                    309:                                break;
                    310:                        }
                    311:  
                    312:                        ddp = DATA_DDP(m2);
                    313:                        nbp = DATA_NBP(m2);
                    314:                        nbp->control  = NBP_LKUP;
                    315:                        NET_ASSIGN(ddp->dst_net, 0);
                    316:                        ddp->dst_node = 255;
                    317:                        dPrintf(D_M_NBP,D_L_INFO, 
                    318:                                ("nbp_input: FWDRQ:loop back for us\n"));
                    319:                        nbp_input(m2, ifID_home);
                    320:                }
                    321:  
                    322:                if (FDDI_OR_TOKENRING(ifID->aa_ifp->if_type))
                    323:                        ddp_bit_reverse(&mcastAddr);
                    324:                ddp_router_output(m, ifID, ET_ADDR,NULL,NULL, &mcastAddr);
                    325:                ddpSent = TRUE;
                    326:                }
                    327:                break;
                    328: 
                    329:        case NBP_BRRQ:
                    330:                {
                    331:                register int    zno;            /* zone table entry numb */
                    332:                register int    ztind;          /* zone bitmap index into RT_entry */
                    333:                register int    ztbit;          /* zone bit to check within above index */
                    334:                register int    zhome=0;        /* true if home zone == destination zone */
                    335:                register int    i;
                    336:                register  gbuf_t        *m2, *m3;
                    337:                register int fromUs = FALSE;
                    338:                register at_socket ourSkt;      /* originating skt */
                    339: 
                    340:                /* for router & MH local only */
                    341:                if ((!(MULTIHOME_MODE && FROM_US(ddp))) && !ROUTING_MODE) {
                    342:                        dPrintf(D_M_NBP,D_L_USR2,
                    343:                                ("nbp_input: BRREQ:non router or MH local\n"));
                    344: 
                    345:                        break;
                    346:                }
                    347:                p = nbp2zone(nbp, gbuf_wptr(m));
                    348:                if ((p == NULL) || !(zno = zt_find_zname(p))) {
                    349:                        break;
                    350:                }
                    351:                if (MULTIHOME_MODE && ifID->ifRouterState == NO_ROUTER) {
                    352:                        ((at_nvestr_t*)p)->len = 1;
                    353:                        ((at_nvestr_t*)p)->str[0] = '*';
                    354:                }
                    355:                if (isZoneLocal((at_nvestr_t*)p)) {
                    356:                        zhome = TRUE;           /* one of our ports is in destination zone */
                    357:                }
                    358:                if (FROM_US(ddp)){      /* save, before we munge it */
                    359:                        fromUs = TRUE;
                    360:                        ourSkt = ddp->src_socket;
                    361:                        dPrintf(D_M_NBP,D_L_USR2,
                    362:                                ("nbp_input:BRRQ from us net:%d\n",
                    363:                                (int)NET_VALUE(ddp->src_net)));
                    364:                }
                    365:                        /* from ZT_CLR_ZMAP */
                    366:                i = zno - 1;
                    367:                ztind = i >> 3;
                    368:                ztbit = 0x80 >> (i % 8);
                    369:                for (i=0,rt=RT_table; i<RT_maxentry; i++,rt++) {
                    370:                        if (!(rt->ZoneBitMap[ztind] & ztbit))           /* if zone not in route, skip*/
                    371:                                continue;
                    372: /*             dPrintf(D_M_NBP, D_L_USR3,
                    373:                        ("nbp_input: BRREQ: port:%d, entry %d\n",
                    374:                                rt->NetPort, i));
                    375: */
                    376: 
                    377:                        ifID = ifID_table[rt->NetPort];
                    378:                        if (!ifID) {
                    379:                                dPrintf(D_M_NBP, D_L_ERROR, 
                    380:                                        ("nbp_input:BRRQ: ifID %s\n", 
                    381:                                        !ifID ? "not found" : "invalid"));
                    382:                                break;
                    383:                        }
                    384: 
                    385:                        ddp = DATA_DDP(m);
                    386:                        ddp->src_node = ifID->ifThisNode.s_node;
                    387:                        NET_ASSIGN(ddp->src_net,  ifID->ifThisNode.s_net);
                    388:                        ddp->src_socket = NBP_SOCKET;
                    389:                        if (!(m2 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) {
                    390:                                dPrintf(D_M_NBP,D_L_ERROR, 
                    391:                                        ("nbp_input: BRREQ:gbuf_copym failed\n"));
                    392:                                break;
                    393:                        }
                    394: 
                    395:                        ddp = DATA_DDP(m2);
                    396:                        nbp = DATA_NBP(m2);
                    397: /*                     nbp->tuple[0].enu_addr.socket = NBP_SOCKET; */
                    398:                        if (MULTIHOME_MODE && fromUs ) {
                    399:                                /* set the return address of the lookup to that of the
                    400:                                   interface it's going out on so that replies come back
                    401:                                   on that net */
                    402:                                dPrintf(D_M_NBP,D_L_USR3, 
                    403:                                   ("nbp_input: BRREQ: src changed to %d.%d.%d\n",
                    404:                                        ifID->ifThisNode.s_net,
                    405:                                        ifID->ifThisNode.s_node, ourSkt));
                    406:                                nbp->tuple[0].enu_addr.net = ifID->ifThisNode.s_net;
                    407:                                nbp->tuple[0].enu_addr.node = ifID->ifThisNode.s_node;
                    408:                                nbp->tuple[0].enu_addr.socket = ourSkt; 
                    409:                                ddp->src_socket = NBP_SOCKET;
                    410:                        }
                    411:                        else
                    412:                                dPrintf(D_M_NBP, D_L_USR3, 
                    413:                                        ("nbp_input: BRREQ: not from us\n"));
                    414: 
                    415:                        dPrintf(D_M_NBP, D_L_USR3,
                    416:                                ("nbp_input dist:%d\n", rt->NetDist));
                    417:                        if (rt->NetDist == 0) {                 /* if direct connect, *we* do the LKUP */
                    418:                                nbp->control  = NBP_LKUP;
                    419:                                NET_ASSIGN(ddp->dst_net, 0);
                    420:                                ddp->dst_node = 255;
                    421:                                if (!zt_get_zmcast(ifID, p, &mcastAddr)) {
                    422:                                        dPrintf(D_M_NBP,D_L_ERROR, 
                    423:                                                ("nbp_input: BRRQ:zt_get_zmcast error\n"));
                    424:                                        break;
                    425:                                }
                    426:                                if (FDDI_OR_TOKENRING(ifID->aa_ifp->if_type))
                    427:                                        ddp_bit_reverse(&mcastAddr);
                    428:                                ddp_router_output(m2, ifID, ET_ADDR, NULL, NULL, &mcastAddr); 
                    429:                        }
                    430:                        else {                                                  /* else fwd to router */
                    431:                                ddp->dst_node = 0;
                    432:                                if (rt->NetStart == 0)          /* if Ltalk */
                    433:                                        NET_ASSIGN(ddp->dst_net, rt->NetStop);
                    434:                                else    
                    435:                                        NET_ASSIGN(ddp->dst_net, rt->NetStart);
                    436:                                nbp->control  = NBP_FWDRQ;
                    437:                                ddp_router_output(m2, ifID, AT_ADDR, 
                    438:                                                  rt->NextIRNet, rt->NextIRNode, 
                    439:                                                  NULL); 
                    440:                        }
                    441:                }
                    442:                if (!zhome)
                    443:                        break;
                    444: 
                    445:                if (!(m3 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) {
                    446:                        dPrintf(D_M_NBP,D_L_ERROR, 
                    447:                                ("nbp_input: BRREQ:gbuf_copym failed\n"));
                    448:                        break;
                    449:                }
                    450: 
                    451:                ddp = DATA_DDP(m3);
                    452:                nbp = DATA_NBP(m3);
                    453:                                
                    454:                nbp->control  = NBP_LKUP;
                    455:                NET_ASSIGN(ddp->dst_net, 0);
                    456:                ddp->dst_node = 255;
                    457:                dPrintf(D_M_NBP,D_L_INFO, ("nbp_input: BRRQ:loop back for us\n"));
                    458:                nbp_input(m3, ifID_home);
                    459:                break;
                    460:                }
                    461: 
                    462:        case NBP_LKUP_REPLY:
                    463:                
                    464:                if (!ROUTING_MODE)      /* for routers only! */
                    465:                        break;
                    466: 
                    467:                dPrintf(D_M_NBP,D_L_WARNING, 
                    468:                        ("nbp_input: routing needed for LKUP_REPLY: from %d.%d\n",
                    469:                         NET_VALUE(ddp->src_net), ddp->src_node));
                    470:                routing_needed(m, ifID, TRUE);
                    471:                ddpSent = TRUE;
                    472:                break;
                    473:                
                    474:        default :
                    475:                dPrintf(D_M_NBP,D_L_ERROR, 
                    476:                        ("nbp_input: unhandled pkt: type:%d\n", nbp->control));
                    477: 
                    478:                routing_needed(m, ifID, TRUE);
                    479:                ddpSent = TRUE;
                    480:                break;
                    481:        } /* switch control */
                    482: 
                    483:        if (!ddpSent)
                    484:                gbuf_freem(m);
                    485:        return;
                    486: } /* nbp_input */
                    487: 
                    488: static int     nbp_validate_n_hash (nbp_req, wild_ok, checkLocal)
                    489:      register nbp_req_t        *nbp_req;
                    490:      register int      wild_ok;
                    491:      register int      checkLocal;     /* if true check if local zone */
                    492: {
                    493:         register at_nvestr_t   *object, *type, *zone;
                    494:        at_nbptuple_t   *tuple;
                    495:        register int    i, part_wild;
                    496: 
                    497:        tuple = DATA_NBP(nbp_req->request)->tuple;
                    498:        nbp_req->flags = 0;
                    499: #ifdef COMMENTED_OUT
                    500:        {
                    501:                int net,node,skt;
                    502:                net = tuple->enu_addr.net;
                    503:                node = tuple->enu_addr.node;
                    504:                skt = tuple->enu_addr.socket;
                    505:                dPrintf(D_M_NBP_LOW,D_L_USR4,
                    506:                        ("nbp_validate: tuple addr:%d:%d:%d\n",net,node,skt));
                    507:        }
                    508: #endif /* COMMENTED_OUT */
                    509: 
                    510:        /* tuple is in the compressed (no "filler") format */
                    511:        object = (at_nvestr_t *)&tuple->enu_entity;
                    512:        type = (at_nvestr_t *)(&object->str[object->len]);
                    513:        zone = (at_nvestr_t *)(&type->str[type->len]);
                    514:        
                    515:        if (object->len > NBP_NVE_STR_SIZE || type->len > NBP_NVE_STR_SIZE || 
                    516:                zone->len > NBP_NVE_STR_SIZE) {
                    517:                dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                    518:                        ("nbp_val_n_hash: bad str len\n"));
                    519:                errno = EINVAL;
                    520:                return (-1);
                    521:        }
                    522:        
                    523: #ifdef NBP_DEBUG
                    524:        {
                    525:                char xzone[35],xobject[35],xtype[35];
                    526:                strncpy(xzone,zone->str, zone->len);
                    527:                strncpy(xobject,object->str, object->len);
                    528:                strncpy(xtype,type->str, type->len);
                    529:                xobject[object->len] = '\0';
                    530:                xzone[zone->len] = '\0';
                    531:                xtype[type->len] = '\0';
                    532:                dPrintf(D_M_NBP_LOW, D_L_USR4,
                    533:                        ("nbp_validate: looking for %s:%s@%s\n",
                    534:                        xobject, xtype, xzone));
                    535:        }
                    536: #endif /* NBP_DEBUG */
                    537:        /* Is this request for our zone ?? */
                    538:        nbp_req->nve.zone.len = zone->len;
                    539:        nbp_req->nve.zone_hash = 0;
                    540:        bcopy(zone->str,nbp_req->nve.zone.str, zone->len);
                    541: 
                    542:        if (checkLocal && !isZoneLocal(zone)) {
                    543:                char str[35];
                    544:                strncpy(str,zone->str,zone->len);
                    545:                str[zone->len] = '\0';
                    546:                dPrintf(D_M_NBP_LOW,D_L_WARNING,
                    547:                        ("nbp_val_n_hash bad zone: %s\n", str));
                    548:                errno = EINVAL;
                    549:                return(-1);
                    550:        }
                    551: 
                    552:        if (!DEFAULT_ZONE(zone)) {
                    553:                nbp_req->nve.zone_hash = nbp_strhash(& nbp_req->nve.zone);
                    554:        }
                    555: 
                    556:        nbp_req->nve.address = tuple->enu_addr;
                    557:        nbp_req->nve.object.len = object->len;
                    558:        nbp_req->nve.object_hash = 0;
                    559:        if (object->len == 1 && (object->str[0] == NBP_ORD_WILDCARD ||
                    560:                object->str[0] == NBP_SPL_WILDCARD)) {
                    561:                if (wild_ok)
                    562:                        nbp_req->flags |= NBP_WILD_OBJECT;
                    563:                else {
                    564:                        dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                    565:                                ("nbp_val_n_hash: wild not okay\n"));
                    566:                        errno = EINVAL;
                    567:                        return (-1);
                    568:                }
                    569:        } else{
                    570:                for (i = part_wild = 0; (unsigned) i<object->len; i++) {
                    571:                        if (object->str[i] == NBP_SPL_WILDCARD)
                    572:                                if (wild_ok)
                    573:                                        if (part_wild) {
                    574:                                          dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                    575:                                                  ("nbp_val_n_hash: too many parts wild\n"));
                    576:                                          errno = EINVAL;
                    577:                                          return (-1);
                    578:                                        } else
                    579:                                          part_wild++;
                    580:                                else {
                    581:                                  dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                    582:                                          ("nbp_val_n_hash: wild not okay2\n"));
                    583:                                  errno = EINVAL;
                    584:                                  return (-1);
                    585:                                }
                    586:                        nbp_req->nve.object.str[i] = object->str[i];
                    587:                }
                    588:                if (!part_wild)
                    589:                        nbp_req->nve.object_hash = 
                    590:                                nbp_strhash(&nbp_req->nve.object);
                    591:        }
                    592: 
                    593:        nbp_req->nve.type.len = type->len;
                    594:        nbp_req->nve.type_hash = 0;
                    595:        if (type->len == 1 && (type->str[0] == NBP_ORD_WILDCARD ||
                    596:                type->str[0] == NBP_SPL_WILDCARD)) {
                    597:                if (wild_ok)
                    598:                        nbp_req->flags |= NBP_WILD_TYPE;
                    599:                else {
                    600:                        dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                    601:                                ("nbp_val_n_hash: wild not okay3\n"));
                    602:                        errno = EINVAL;
                    603:                        return (-1);
                    604:                }
                    605:        } else {
                    606:                for (i = part_wild = 0; (unsigned) i<type->len; i++) {
                    607:                        if (type->str[i] == NBP_SPL_WILDCARD)
                    608:                                if (wild_ok)
                    609:                                        if (part_wild) {
                    610:                                          dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                    611:                                                  ("nbp_val_n_hash: too many parts wild2\n"));
                    612:                                          errno = EINVAL;
                    613:                                          return (-1);
                    614:                                        } else
                    615:                                          part_wild++;
                    616:                                else {
                    617:                                        errno = EINVAL;
                    618:                                        return (-1);
                    619:                                }
                    620:                        nbp_req->nve.type.str[i] = type->str[i];
                    621:                }
                    622:                if (!part_wild)
                    623:                        nbp_req->nve.type_hash = 
                    624:                                nbp_strhash(&nbp_req->nve.type);
                    625:        }
                    626: #ifdef NBP_DEBUG
                    627:        {
                    628:                char zone[35],object[35],type[35];
                    629:                strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len);
                    630:                strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len);
                    631:                strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len);
                    632:                object[nbp_req->nve.object.len] = '\0';
                    633:                zone[nbp_req->nve.zone.len] = '\0';
                    634:                type[nbp_req->nve.type.len] = '\0';
                    635:                dPrintf(D_M_NBP_LOW,D_L_USR4,
                    636:                        ("nbp_validate: after hash: %s:%s@%s\n",
                    637:                        object, type, zone));
                    638:        }
                    639: #endif /* NBP_DEBUG */
                    640:        return(0);
                    641: } /* nbp_validate_n_hash */
                    642: 
                    643: 
                    644: /* Upshifts in place */
                    645: static void    nbp_upshift (str, count)
                    646: register u_char        *str;
                    647: register int   count;
                    648: {
                    649:        register int    i, j;
                    650:        register u_char ch;
                    651:        static  unsigned char   lower_case[] =
                    652:                {0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0xbe,
                    653:                 0xbf, 0xcf, 0x9b, 0x8b, 0x88, 0};
                    654:        static  unsigned char   upper_case[] = 
                    655:                {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xae,
                    656:                 0xaf, 0xce, 0xcd, 0xcc, 0xcb, 0};
                    657: 
                    658:        for (j=0 ; j<count ; j++) {
                    659:                ch = str[j];
                    660:                if (ch >= 'a' && ch <= 'z')
                    661:                        str[j] = ch + 'A' - 'a';
                    662:                else if (ch & 0x80)
                    663:                        for (i=0; lower_case[i]; i++)
                    664:                                if (ch == lower_case[i])
                    665:                                        str[j] = upper_case[i];
                    666:        }
                    667: }
                    668: 
                    669: 
                    670: u_int nbp_strhash (nvestr)
                    671:      register at_nvestr_t      *nvestr;
                    672: {
                    673:        /* upshift while hashing */
                    674:        register u_int  hash = 0;
                    675:        register int    i, len;
                    676:        union {
                    677:                u_char  h_4char[4];
                    678:                int     h_int;
                    679:        } un;
                    680: 
                    681:        for (i=0; (unsigned) i < nvestr->len; i+=sizeof(int)) {
                    682:                len = MIN((nvestr->len-i), sizeof(int));
                    683:                if (len == sizeof(int))
                    684:                        bcopy(&(nvestr->str[i]), &un, sizeof(un));
                    685:                else {
                    686:                        un.h_int = -1;
                    687:                        for ( ; (unsigned) i<nvestr->len; i++)
                    688:                                un.h_4char[i % sizeof(int)] = nvestr->str[i];
                    689:                }
                    690:                nbp_upshift (un.h_4char, len);
                    691:                hash ^= un.h_int;
                    692:        }
                    693:        
                    694:        return (hash);
                    695: } /* nbp_strhash */
                    696: 
                    697: static nve_entry_t *nbp_search_nve (nbp_req, ifID)
                    698:      register nbp_req_t        *nbp_req;
                    699:      register at_ifaddr_t      *ifID;          /* NULL ok */
                    700: {
                    701:        register nve_entry_t    *nve_entry;
                    702: 
                    703: #ifdef NBP_DEBUG
                    704:        {
                    705:                char zone[35],object[35],type[35];
                    706:                strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len);
                    707:                strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len);
                    708:                strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len);
                    709:                object[nbp_req->nve.object.len] = '\0';
                    710:                zone[nbp_req->nve.zone.len] = '\0';
                    711:                type[nbp_req->nve.type.len] = '\0';
                    712:                dPrintf(D_M_NBP_LOW, D_L_USR4,
                    713:                                ("nbp_search: looking for %s:%s@%s resp:0x%x\n",object,type,zone,
                    714:                                (u_int) nbp_req->response));
                    715:        }
                    716: #endif /* NBP_DEBUG */
                    717:        ATDISABLE(nve_lock_pri,NVE_LOCK);
                    718:        TAILQ_FOREACH(nve_entry, &name_registry, nve_link) {
                    719:                if ((nbp_req->nve.zone_hash) && 
                    720:                        ((nbp_req->nve.zone_hash != 
                    721:                          nve_entry->zone_hash) &&
                    722:                         (nbp_req->nve.zone_hash != hzonehash)
                    723:                    )
                    724:                   ) {
                    725:                        dPrintf(D_M_NBP_LOW,D_L_USR4,
                    726:                                ("nbp_search: no match for zone, req hash:%x\n",
                    727:                        nbp_req->nve.zone_hash));
                    728:                        continue;
                    729:                }
                    730:                else {  /* for this entry's zone OR no zone in request or entry */
                    731:                        /* only in singleport mode (!MULTIPORT_MODE) with 
                    732:                           empty PRAM can an entry have '*' for it's zone
                    733:                        */
                    734:                        at_nvestr_t *ezone=&nve_entry->zone;
                    735:                        at_nvestr_t *rzone=&nbp_req->nve.zone;
                    736:                        if (!DEFAULT_ZONE(rzone) && !DEFAULT_ZONE(ezone))  {
                    737:                                if (nbp_strcmp (rzone, ezone, 0) != 0)
                    738:                                        continue;
                    739:                        }
                    740:                        else {
                    741:                            if (MULTIHOME_MODE && ifID && 
                    742:                                (nve_entry->address.net != 
                    743:                                 ifID->ifThisNode.s_net)) {
                    744:                                dPrintf(D_M_NBP, D_L_USR4, 
                    745:                                        ("nbp search ifID (%d) & req net (%d) not eq\n",
                    746:                                         nve_entry->address.net,
                    747:                                         ifID->ifThisNode.s_net));
                    748:                                continue;
                    749:                            }
                    750:                            if (ifID)
                    751:                                dPrintf(D_M_NBP, D_L_USR4, 
                    752:                                        ("nbp search ifID (%d) & req net (%d)  equal\n",
                    753:                                         nve_entry->address.net,
                    754:                                         ifID->ifThisNode.s_net));
                    755:                        }
                    756:                
                    757:                }
                    758:                if (!(nbp_req->flags & NBP_WILD_OBJECT)) {
                    759:                        if ((nbp_req->nve.object_hash) && 
                    760:                                (nbp_req->nve.object_hash != 
                    761:                                nve_entry->object_hash))
                    762:                                continue;
                    763:                        else {
                    764:                                if (nbp_strcmp (&nbp_req->nve.object, 
                    765:                                        &nve_entry->object, 
                    766:                                        NBP_SPL_WILDCARD) != 0)
                    767:                                        continue;
                    768:                        }
                    769:                }
                    770: 
                    771: 
                    772:                if (!(nbp_req->flags & NBP_WILD_TYPE)) {
                    773:                        if ((nbp_req->nve.type_hash) && 
                    774:                                (nbp_req->nve.type_hash !=nve_entry->type_hash))
                    775:                                continue;
                    776:                        else {
                    777:                                if (nbp_strcmp (&nbp_req->nve.type, 
                    778:                                        &nve_entry->type, 
                    779:                                        NBP_SPL_WILDCARD) != 0)
                    780:                                        continue;
                    781:                        }
                    782:                }
                    783: 
                    784:                /* Found a match! */
                    785: #ifdef NBP_DEBUG
                    786:        {
                    787:                char zone[35],object[35],type[35];
                    788: 
                    789:                strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len);
                    790:                strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len);
                    791:                strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len);
                    792:                object[nbp_req->nve.object.len] = '\0';
                    793:                zone[nbp_req->nve.zone.len] = '\0';
                    794:                type[nbp_req->nve.type.len] = '\0';
                    795:                dPrintf(D_M_NBP_LOW, D_L_USR2,
                    796:                        ("nbp_search: found  %s:%s@%s  net:%d\n",
                    797:                        object, type, zone, (int)nve_entry->address.net));
                    798:        }
                    799: #endif /* NBP_DEBUG */
                    800:                if (nbp_req->func != NULL) {
                    801:                        if ((*(nbp_req->func))(nbp_req, nve_entry) != 0) {
                    802:                                /* errno expected to be set by func */
                    803:                                ATENABLE(nve_lock_pri,NVE_LOCK);
                    804:                                return (NULL);
                    805:                        }
                    806:                } else {
                    807:                        ATENABLE(nve_lock_pri,NVE_LOCK);
                    808:                        return (nve_entry);
                    809:                }
                    810:        }
                    811:        ATENABLE(nve_lock_pri,NVE_LOCK);
                    812: 
                    813:        errno = 0;
                    814:        return (NULL);
                    815: } /* nbp_search_nve */
                    816: 
                    817: static int     nbp_lkup_reply (nbp_req, nve_entry)
                    818: register nbp_req_t     *nbp_req;
                    819: register nve_entry_t   *nve_entry;
                    820: {
                    821:        register at_nbptuple_t  *tuple;
                    822:        register int    tuple_size, buf_len;
                    823:        register int    obj_len, type_len;
                    824:        u_char *p;
                    825: 
                    826:        /* size of the current tuple we want to write... */
                    827:        tuple_size = nve_entry->object.len + 1 +        /* object */
                    828:                        nve_entry->type.len + 1 +       /* type */
                    829:                        2 +                             /* zone */
                    830:                        sizeof (at_inet_t) + 1;         /* addr + enum */
                    831: 
                    832:        buf_len = ((nbp_req->flags & NBP_WILD_MASK) ? DDP_DATA_SIZE:tuple_size);
                    833:        if (nbp_req->response == NULL) {
                    834:                if (nbp_setup_resp (nbp_req, buf_len) != 0)
                    835:                        /* errno expected to be set by nbp_setup_resp() */
                    836:                        return (-1);
                    837:        }
                    838: 
                    839:        if ((nbp_req->space_unused < tuple_size) || 
                    840:                (DATA_NBP(nbp_req->response)->tuple_count == NBP_TUPLE_MAX)) {
                    841:                if (nbp_send_resp (nbp_req) != 0)
                    842:                        return (-1);
                    843:                if (nbp_setup_resp (nbp_req, buf_len) != 0)
                    844:                        return (-1);
                    845:        }
                    846: 
                    847:        /* At this point, we have a response buffer that can accommodate the
                    848:         * tuple we want to write. Write it!
                    849:         */
                    850:        tuple = (at_nbptuple_t *)gbuf_wptr(nbp_req->response);
                    851:        tuple->enu_addr = nve_entry->address;
                    852:        tuple->enu_enum = nve_entry->enumerator;
                    853: 
                    854:         /* tuple is in the compressed (no "filler") format */
                    855:        p = (u_char *)&tuple->enu_entity.object;
                    856:        obj_len = nve_entry->object.len + 1;
                    857:        bcopy(&nve_entry->object, p, obj_len);
                    858:        p += obj_len;
                    859:        type_len = nve_entry->type.len + 1;
                    860:        bcopy(&nve_entry->type, p, type_len);
                    861:        p += type_len;
                    862:        p[0] = (u_char)1;
                    863:        p[1] = '*';
                    864:                                                                                
                    865:        nbp_req->space_unused -= tuple_size;
                    866:        gbuf_winc(nbp_req->response, tuple_size);
                    867: 
                    868:        /* increment the tuple count in header by 1 */
                    869:        DATA_NBP(nbp_req->response)->tuple_count++;
                    870: 
                    871:        return (0);
                    872: }
                    873: 
                    874: 
                    875: static int     nbp_strcmp (str1, str2, embedded_wildcard)
                    876: register at_nvestr_t   *str1, *str2;
                    877: register u_char        embedded_wildcard;      /* If str1 may contain a character
                    878:                                         * that's to be treated as an
                    879:                                         * embedded wildcard, this character
                    880:                                         * is it.  Making this special case
                    881:                                         * since for zone names, squiggly
                    882:                                         * equal is not to be treated as a 
                    883:                                         * wildcard.
                    884:                                         */
                    885: {
                    886:        u_char          ch1,ch2;
                    887:        register int    i1, i2;
                    888:        register int    reverse = 0;
                    889:        register int    left_index;
                    890: 
                    891:        /* Embedded wildcard, if any, could only be in the first string (str1).
                    892:         * returns 0 if two strings are equal (modulo case), -1 otherwise 
                    893:         */
                    894:        
                    895:        if (str1->len == 0 || str2->len == 0) {
                    896:                return (-1);
                    897:        }       
                    898:        
                    899:        /* Wildcards are not allowed in str2.
                    900:         *
                    901:         * If str1 could potentially contain an embedded wildcard, since the
                    902:         * embedded wildcard matches ZERO OR MORE characters, str1 can not be
                    903:         * more than 1 character longer than str2.
                    904:         *
                    905:         * If str1 is not supposed to have embedded wildcards, the two strs 
                    906:         * must be of equal length.
                    907:         */
                    908:        if ((embedded_wildcard && (str2->len < (unsigned) (str1->len-1))) ||
                    909:                (!embedded_wildcard && (str2->len !=  str1->len))) {
                    910:                return (-1);
                    911:        }
                    912: 
                    913:        for (i1 = i2 = left_index = 0; (unsigned) i1 < str1->len ;) {
                    914:                ch1 = str1->str[i1];
                    915:                ch2 = str2->str[i2];
                    916: 
                    917:                if (embedded_wildcard && (ch1==embedded_wildcard)) {
                    918:                        /* hit the embedded wild card... start comparing from 
                    919:                         * the other end of the string.
                    920:                         */
                    921:                        reverse++;
                    922:                        /* But, if embedded wildcard was the last character of 
                    923:                         * the string, the two strings match, so return okay.
                    924:                         */
                    925:                        if (i1 == str1->len-1) {
                    926:                                return (0);
                    927:                        }
                    928:                        
                    929:                        i1 = str1->len - 1;
                    930:                        i2 = str2->len - 1;
                    931:                        
                    932:                        continue;
                    933:                }
                    934:                
                    935:                nbp_upshift(&ch1, 1);
                    936:                nbp_upshift(&ch2, 1);
                    937: 
                    938:                if (ch1 != ch2) {
                    939:                        return (-1);
                    940:                }
                    941:                
                    942:                if (reverse) {
                    943:                        i1--; i2--;
                    944:                        if (i1 == left_index) {
                    945:                                return (0);
                    946:                        }
                    947:                } else {
                    948:                        i1++; i2++; left_index++;
                    949:                }
                    950:        }
                    951:        return (0);
                    952: }
                    953: 
                    954: 
                    955: static void    nbp_setup_hdr (nbp_req)
                    956: register nbp_req_t     *nbp_req;
                    957: {
                    958:        register at_ddp_t       *ddp;
                    959:        register at_nbp_t       *nbp;
                    960: 
                    961:        ddp = DATA_DDP(nbp_req->response);
                    962:        nbp = DATA_NBP(nbp_req->response);
                    963:        
                    964:        ddp->type = DDP_NBP;
                    965:        UAS_ASSIGN(ddp->checksum, 0);
                    966:        ddp->unused = ddp->hopcount = 0;
                    967: 
                    968:        switch(DATA_NBP(nbp_req->request)->control) {
                    969:        case NBP_LKUP :
                    970:                ddp->dst_socket = nbp_req->nve.address.socket;
                    971:                ddp->dst_node = nbp_req->nve.address.node;
                    972:                NET_ASSIGN(ddp->dst_net, nbp_req->nve.address.net);
                    973:                nbp->control = NBP_LKUP_REPLY;
                    974:                break;
                    975:        }
                    976:        nbp->at_nbp_id = DATA_NBP(nbp_req->request)->at_nbp_id;
                    977:        return;
                    978: }
                    979: 
                    980: 
                    981: static int     nbp_setup_resp (nbp_req, tuples_size)
                    982: register nbp_req_t     *nbp_req;
                    983: register int           tuples_size;
                    984: {
                    985:        int     buf_size = tuples_size + DDP_X_HDR_SIZE + NBP_HDR_SIZE;
                    986:        nbp_req->response = gbuf_alloc(AT_WR_OFFSET+buf_size, PRI_MED);
                    987:        if (nbp_req->response == NULL) {
                    988:                errno = ENOBUFS;
                    989:                return(-1);
                    990:        }
                    991:        gbuf_rinc(nbp_req->response, AT_WR_OFFSET);
                    992:        gbuf_wset(nbp_req->response, DDP_X_HDR_SIZE + NBP_HDR_SIZE);
                    993:        nbp_setup_hdr(nbp_req);
                    994: 
                    995:        DATA_NBP(nbp_req->response)->tuple_count = 0;
                    996:        nbp_req->space_unused = tuples_size;
                    997: 
                    998:        return (0);
                    999: } /* nbp_setup_resp */
                   1000: 
                   1001: 
                   1002: static int     nbp_send_resp (nbp_req)
                   1003: register nbp_req_t     *nbp_req;
                   1004: {
                   1005:        int             status;
                   1006: 
                   1007:        status = ddp_output(&nbp_req->response, (at_socket)NBP_SOCKET, FALSE);
                   1008:        nbp_req->response = NULL;
                   1009:        errno = status;
                   1010:        return(errno?-1:0);
                   1011: }
                   1012: 
                   1013: void nbp_add_multicast(zone, ifID)
                   1014:      at_nvestr_t *zone;
                   1015:      at_ifaddr_t *ifID;
                   1016: {
                   1017:        char data[ETHERNET_ADDR_LEN];
                   1018:        int i;
                   1019: 
                   1020:        if (zone->str[0] == '*')
                   1021:                return;
                   1022: 
                   1023:        {
                   1024:          char str[35];
                   1025:          strncpy(str,zone->str,zone->len);
                   1026:          str[zone->len] = '\0';
                   1027:          dPrintf(D_M_NBP_LOW, D_L_USR3,
                   1028:                  ("nbp_add_multi getting mc for %s\n", str));
                   1029:        }
                   1030:        zt_get_zmcast(ifID, zone, data); 
                   1031:        if (FDDI_OR_TOKENRING(ifID->aa_ifp->if_type))
                   1032:          ddp_bit_reverse(data);
                   1033:        dPrintf(D_M_NBP_LOW,D_L_USR3,
                   1034:                ("nbp_add_multi adding  0x%x%x port:%d ifID:0x%x if:%s\n",
                   1035:                 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
                   1036:                 i, (u_int) ifID, ifID->ifName));
                   1037: 
                   1038:        bcopy((caddr_t)data, (caddr_t)&ifID->ZoneMcastAddr, ETHERNET_ADDR_LEN);
                   1039:        (void)at_reg_mcast(ifID, (caddr_t)&ifID->ZoneMcastAddr);
                   1040: }
                   1041: 
                   1042: 
                   1043: getNbpTableSize()
                   1044: 
                   1045: /* for SNMP, returns size in # of entries */
                   1046: {
                   1047:        register nve_entry_t *nve;
                   1048:        register int i=0;
                   1049: 
                   1050:        ATDISABLE(nve_lock_pri,NVE_LOCK);
                   1051:        for (nve = TAILQ_FIRST(&name_registry); nve; nve = TAILQ_NEXT(nve, nve_link), i++)
                   1052:                i++;
                   1053:        ATENABLE(nve_lock_pri,NVE_LOCK);
                   1054:        return(i);
                   1055: }
                   1056: 
                   1057: getNbpTable(p, s, c)
                   1058:      snmpNbpEntry_t    *p;
                   1059:      int               s;              /* starting entry */
                   1060:      int               c;              /* # entries to copy */
                   1061: 
                   1062: /* for SNMP, returns section of nbp table */
                   1063: {
                   1064:        register nve_entry_t *nve;
                   1065:        register int i=0;
                   1066:        static   int nextNo=0;          /* entry that *next points to */
                   1067:        static   nve_entry_t  *next = (nve_entry_t*)NULL;
                   1068:        
                   1069:        if (s && next && nextNo == s) {
                   1070:                nve = next;
                   1071:                i = nextNo;
                   1072:        }
                   1073:        else
                   1074:                nve = TAILQ_FIRST(&name_registry);
                   1075: 
                   1076:        ATDISABLE(nve_lock_pri,NVE_LOCK);
                   1077:        for ( ; nve && c ; nve = TAILQ_NEXT(nve, nve_link), p++,i++) {
                   1078:                if (i>= s) {
                   1079:                        p->nbpe_object = nve->object;
                   1080:                        p->nbpe_type   = nve->type;
                   1081:                        c--;
                   1082:                }
                   1083:        }
                   1084:        ATENABLE(nve_lock_pri,NVE_LOCK);
                   1085:        if (nve) {
                   1086:                next = nve;
                   1087:                nextNo = i;
                   1088:        } else {
                   1089:                next = (nve_entry_t*)NULL;
                   1090:                nextNo = 0;
                   1091:        }
                   1092: }
                   1093: 
                   1094: 
                   1095: #define ZONES_PER_BLK          31      /* 31 fits within a 1k blk) */
                   1096: #define ZONE_BLK_SIZE          ZONES_PER_BLK * sizeof(at_nvestr_t)
                   1097: 
                   1098: int setLocalZones(newzones, size)
                   1099:      at_nvestr_t *newzones;
                   1100:      int size;
                   1101: /* updates list of zones which are local to all active ports
                   1102:    missing zones are not deleted, only missing zones are added.
                   1103: */
                   1104: {
                   1105:        int     bytesread=0;            /* #bytes read from tuple */
                   1106:        int i=0, dupe;
                   1107:        gbuf_t  *m;
                   1108:        at_nvestr_t             *pnve, *pnew = newzones;
                   1109: 
                   1110:        if (!lzones) {
                   1111:                if(!(lzones = gbuf_alloc(ZONE_BLK_SIZE, PRI_MED)))
                   1112:                        return(ENOBUFS);
                   1113:                gbuf_wset(lzones,0);
                   1114:        }
                   1115:        while (bytesread < size) {              /* for each new zone */
                   1116:                {
                   1117:                        char str[35];
                   1118:                        strncpy(str,pnew->str,pnew->len);
                   1119:                        str[pnew->len] = '\0';
                   1120:                }
                   1121:                m = lzones;                             
                   1122:                pnve = (at_nvestr_t*)gbuf_rptr(m);
                   1123:                dupe = 0;
                   1124:                for (i=0; i<lzonecnt && !dupe; i++,pnve++)  {
                   1125:                        if (i && !(i%ZONES_PER_BLK))
                   1126:                                if (gbuf_cont(m)) {
                   1127:                                        m = gbuf_cont(m);
                   1128:                                        pnve = (at_nvestr_t*)gbuf_rptr(m);
                   1129:                                }
                   1130:                                else
                   1131:                                        break;
                   1132:                        if (pnew->len != pnve->len)
                   1133:                                continue;
                   1134:                        if (pnew->len > 33) {
                   1135:                                return(0);
                   1136:                        }
                   1137:                        if (!strncmp(pnew->str, pnve->str, pnew->len)) {
                   1138:                                dupe=1;
                   1139:                                continue;
                   1140:                        }
                   1141:                }
                   1142:                if (!dupe) {
                   1143:                        /* add new zone */
                   1144:                        if (lzonecnt && !(lzonecnt%ZONES_PER_BLK)) {
                   1145:                                if(!(gbuf_cont(m) = gbuf_alloc(ZONE_BLK_SIZE, PRI_MED)))
                   1146:                                        return(ENOBUFS);
                   1147:                                gbuf_wset(gbuf_cont(m),0);
                   1148:                                pnve = (at_nvestr_t*)gbuf_rptr(gbuf_cont(m));
                   1149:                        }
                   1150:                        strncpy(pnve->str,pnew->str,pnew->len);
                   1151:                        pnve->len = pnew->len;
                   1152:                        lzonecnt++;
                   1153:                }
                   1154:                bytesread += (pnew->len+1);
                   1155:                pnew = (at_nvestr_t*) (((char *)pnew) + pnew->len + 1);
                   1156:        }
                   1157:        /* showLocalZones1(); */
                   1158:        return(0);
                   1159: }
                   1160: 
                   1161: /**********
                   1162: showLocalZones1()
                   1163: {
                   1164:        int i;
                   1165:        at_nvestr_t *pnve;
                   1166:        gbuf_t  *m;
                   1167:        char str[35];
                   1168:        
                   1169:        for (i=0;  ; i++) {
                   1170:                if (!(pnve = getLocalZone(i))) {
                   1171:                        break;
                   1172:                }
                   1173:                strncpy(str,pnve->str,pnve->len);
                   1174:                str[pnve->len] = '\0';
                   1175:        }
                   1176: }
                   1177: 
                   1178: *********/
                   1179: 
                   1180: isZoneLocal(zone)
                   1181: at_nvestr_t *zone;
                   1182: {
                   1183:        at_nvestr_t *pnve;
                   1184:        int i;
                   1185:        if (DEFAULT_ZONE(zone))
                   1186:                return(1);
                   1187:        for (i=0;  ; i++) {
                   1188:                if (!(pnve = getLocalZone(i))) 
                   1189:                        break;
                   1190:                if (!nbp_strcmp(pnve,zone,0))
                   1191:                        return(1);
                   1192:        }
                   1193:        return(0);
                   1194: }
                   1195:        
                   1196: 
                   1197: #define NULL_PNVESTR (at_nvestr_t *) 0
                   1198: 
                   1199: at_nvestr_t *getLocalZone(zno)
                   1200:        int zno;                        /* zone number in virtual list to
                   1201:                                           return, 0 for first zone */
                   1202: /* returns pointer to a new local zone number zno,
                   1203:    returns null when no zones left.
                   1204: */
                   1205: {
                   1206:        if_zone_t ifz;
                   1207:        ifz.ifzn.zone = zno;
                   1208:        if (MULTIPORT_MODE) 
                   1209:                return(getRTRLocalZone(&ifz));
                   1210:        else
                   1211:                return(getSPLocalZone(zno));
                   1212: }
                   1213: 
                   1214: 
                   1215: at_nvestr_t *getSPLocalZone(zno)
                   1216:        int zno;                        /* zone number in virtual list to
                   1217:                                                   return, 0 for first zone */
                   1218: /* single port mode version */
                   1219: {
                   1220:        int curz=0;             /* current zone */
                   1221:        gbuf_t *m;
                   1222:        at_nvestr_t *pnve;
                   1223: 
                   1224:        if (lzones) {
                   1225:                m = lzones;
                   1226:                pnve = (at_nvestr_t*)gbuf_rptr(m);
                   1227:        }
                   1228:        else
                   1229:                return(NULL_PNVESTR);
                   1230:        if ( zno>=lzonecnt )
                   1231:                return(NULL_PNVESTR);
                   1232:        for (curz=0; curz<zno; curz++,pnve++ ) {
                   1233:                if ( curz<lzonecnt ) {
                   1234:                        if (curz && !(curz%ZONES_PER_BLK) ) {
                   1235:                                if (gbuf_cont(m)) {
                   1236:                                        m = gbuf_cont(m);
                   1237:                                        pnve = (at_nvestr_t*)gbuf_rptr(m);
                   1238:                                }
                   1239:                                else {
                   1240:                                        return(NULL_PNVESTR);
                   1241:                                }
                   1242:                        }
                   1243:                        if (pnve->len > NBP_NVE_STR_SIZE) {
                   1244:                                return(NULL_PNVESTR);
                   1245:                        }
                   1246:                }
                   1247:                else
                   1248:                        return(NULL_PNVESTR);
                   1249:        }
                   1250:        return(pnve);
                   1251: }
                   1252: 
                   1253: /* The following functions are used in name registration and removal */
                   1254: 
                   1255: int nbp_fillin_nve(entity, nve)
                   1256:      at_entity_t       *entity;
                   1257:      nve_entry_t       *nve;
                   1258: {
                   1259:        register int i;
                   1260: 
                   1261:        if (entity->object.len > NBP_NVE_STR_SIZE || 
                   1262:            entity->type.len > NBP_NVE_STR_SIZE || 
                   1263:            entity->zone.len > NBP_NVE_STR_SIZE) {
                   1264:                dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                   1265:                        ("nbp_fillin_nve: bad str len\n"));
                   1266:                errno = EINVAL;
                   1267:                return (-1);
                   1268:        }
                   1269:        
                   1270:        nve->zone = entity->zone;
                   1271:        nve->zone_hash = 0;
                   1272:        if (!isZoneLocal(&entity->zone)) {
                   1273:                errno = EINVAL;
                   1274:                return(-1);
                   1275:        }
                   1276:        /* if there's no zone, '*' gets filled in when entry is created */
                   1277:        if (!DEFAULT_ZONE(&entity->zone))
                   1278:                nve->zone_hash = nbp_strhash(&nve->zone);
                   1279: 
                   1280:        nve->object = entity->object;
                   1281:        nve->object_hash = 0;
                   1282:        if (entity->object.len == 1 && 
                   1283:            (entity->object.str[0] == NBP_ORD_WILDCARD ||
                   1284:             entity->object.str[0] == NBP_SPL_WILDCARD)) {
                   1285:                dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                   1286:                        ("nbp_fillin_nve: wildcard\n"));
                   1287:                errno = EINVAL;
                   1288:                return (-1);
                   1289:        }
                   1290:        for (i = 0; i < entity->object.len; i++) {
                   1291:                if (entity->object.str[i] == NBP_SPL_WILDCARD) {
                   1292:                dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                   1293:                        ("nbp_fillin_nve: wildcard2\n"));
                   1294:                        errno = EINVAL;
                   1295:                        return (-1);
                   1296:                }
                   1297:        }
                   1298:        nve->object_hash = nbp_strhash(&nve->object);
                   1299: 
                   1300:        nve->type = entity->type;
                   1301:        nve->type_hash = 0;
                   1302:        if (entity->type.len == 1 && 
                   1303:            (entity->type.str[0] == NBP_ORD_WILDCARD ||
                   1304:             entity->type.str[0] == NBP_SPL_WILDCARD)) {
                   1305:                errno = EINVAL;
                   1306:                return (-1);
                   1307:        }
                   1308:        for (i = 0; i < entity->type.len; i++) {
                   1309:                if (entity->type.str[i] == NBP_SPL_WILDCARD) {
                   1310:                dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                   1311:                        ("nbp_fillin_nve: wildcard3\n"));
                   1312:                        errno = EINVAL;
                   1313:                        return (-1);
                   1314:                }
                   1315:        }
                   1316:        nve->type_hash = nbp_strhash(&nve->type);
                   1317: 
                   1318:        return(0);
                   1319: } /* nbp_fillin_nve */
                   1320: 
                   1321: nve_entry_t *nbp_find_nve(nve)
                   1322:      nve_entry_t *nve;
                   1323: {
                   1324:        register nve_entry_t    *nve_entry;
                   1325: 
                   1326:        ATDISABLE(nve_lock_pri,NVE_LOCK);
                   1327:        TAILQ_FOREACH(nve_entry, &name_registry, nve_link) {
                   1328:                if (nve->zone_hash &&
                   1329:                    ((nve->zone_hash != nve_entry->zone_hash) &&
                   1330:                     (nve->zone_hash != hzonehash))) {
                   1331:                        dPrintf(D_M_NBP_LOW,D_L_USR4,
                   1332:                                ("nbp_find_nve: no match for zone, req hash:%x\n",
                   1333:                                 nve->zone_hash));
                   1334:                        continue;
                   1335:                } 
                   1336: 
                   1337:                if ((nve->object_hash) && 
                   1338:                    (nve->object_hash != nve_entry->object_hash))
                   1339:                        continue;
                   1340: 
                   1341:                if ((nve->type_hash) && 
                   1342:                    (nve->type_hash != nve_entry->type_hash))
                   1343:                        continue;
                   1344: 
                   1345:                /* Found a match! */
                   1346:                ATENABLE(nve_lock_pri,NVE_LOCK);
                   1347:                return (nve_entry);
                   1348:        }
                   1349:        ATENABLE(nve_lock_pri,NVE_LOCK);
                   1350: 
                   1351:        return (NULL);
                   1352: } /* nbp_find_nve */
                   1353: 
                   1354: static int nbp_enum_gen (nve_entry)
                   1355:      register nve_entry_t      *nve_entry;
                   1356: {
                   1357:        register int            new_enum = 0;
                   1358:        register nve_entry_t    *ne;
                   1359: 
                   1360:        ATDISABLE(nve_lock_pri,NVE_LOCK);
                   1361: re_do:
                   1362:        TAILQ_FOREACH(ne, &name_registry, nve_link) {
                   1363:                if ((*(int *)&ne->address == *(int *)&nve_entry->address) &&
                   1364:                        (ne->enumerator == new_enum)) {
                   1365:                        if (new_enum == 255) {
                   1366:                                ATENABLE(nve_lock_pri,NVE_LOCK);
                   1367:                                return(EADDRNOTAVAIL);
                   1368:                        } else {
                   1369:                                new_enum++;
                   1370:                                goto re_do;
                   1371:                        }
                   1372:                }
                   1373:        }
                   1374: 
                   1375:        ATENABLE(nve_lock_pri,NVE_LOCK);
                   1376:        nve_entry->enumerator = new_enum;
                   1377:        return (0);
                   1378: }
                   1379: 
                   1380: int nbp_new_nve_entry(nve_entry, ifID)
                   1381:      nve_entry_t *nve_entry;
                   1382:      at_ifaddr_t *ifID;
                   1383: {
                   1384:        gbuf_t          *tag;
                   1385:        nve_entry_t     *new_entry;
                   1386:        at_nvestr_t     *zone;
                   1387:        int error;
                   1388: 
                   1389:        if (!(valid_at_addr((at_inet_t *)&nve_entry->address))) {
                   1390:                dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                   1391:                        ("nbp_new_nve_entry: valid_at_addr\n"));
                   1392:                return(EINVAL);
                   1393:        }
                   1394:        if ((error = nbp_enum_gen(nve_entry)))
                   1395:                return(error);
                   1396: 
                   1397:        nve_entry->unique_nbp_id = ++nbp_id_count;
                   1398: 
                   1399:        /* Got an nve entry on hand.... allocate a buffer, copy the entry
                   1400:         * on to it and stick it in the registry.
                   1401:         */
                   1402:        if ((tag = gbuf_alloc(sizeof(nve_entry_t), PRI_HI)) == NULL){
                   1403:                return(ENOBUFS);
                   1404:        }
                   1405:        gbuf_wset(tag, sizeof(nve_entry_t));
                   1406:        new_entry = (nve_entry_t *)gbuf_rptr(tag);
                   1407:        bcopy(nve_entry, new_entry, sizeof(nve_entry_t));
                   1408: 
                   1409:        if (DEFAULT_ZONE(&nve_entry->zone)) {
                   1410:           /* put actual zone name in entry instead of "*" */
                   1411:           /* if single port mode and no zone name, then a router
                   1412:              is down, so use pram zone name hint from elap cfg */
                   1413:                if (!MULTIPORT_MODE && ifID_home->ifZoneName.str[0] == '*') {
                   1414:                        zone = &ifID_home->startup_zone;
                   1415:                } else {
                   1416:                        zone = &ifID_home->ifZoneName; 
                   1417:                }
                   1418:                new_entry->zone = *zone;
                   1419:                if ( new_entry->zone.len == 0 ) {
                   1420:                        new_entry->zone.str[0] = '*';
                   1421:                        new_entry->zone.len = 1;
                   1422:                }
                   1423:                new_entry->zone_hash = nbp_strhash(&new_entry->zone);
                   1424:        }
                   1425:        new_entry->tag = tag;
                   1426:        new_entry->pid =  current_proc()->p_pid;
                   1427: 
                   1428:        ATDISABLE(nve_lock_pri,NVE_LOCK);
                   1429:        TAILQ_INSERT_TAIL(&name_registry, new_entry, nve_link);
                   1430:        ATENABLE(nve_lock_pri,NVE_LOCK);
                   1431:        at_state.flags |= AT_ST_NBP_CHANGED;
                   1432: 
                   1433: #ifdef NBP_DEBUG
                   1434:        {
                   1435:                char zone[35],object[35],type[35];
                   1436:                strncpy(zone,new_entry->zone.str, new_entry->zone.len);
                   1437:                strncpy(object,new_entry->object.str, new_entry->object.len);
                   1438:                strncpy(type,new_entry->type.str, new_entry->type.len);
                   1439:                object[new_entry->object.len] = '\0';
                   1440:                zone[new_entry->zone.len] = '\0';
                   1441:                type[new_entry->type.len] = '\0';
                   1442:                dPrintf(D_M_NBP_LOW, D_L_USR4,
                   1443:                        ("nbp_insert: adding %s:%s@%s addr:%d.%d ",
                   1444:                         object, type, zone, 
                   1445:                         new_entry->address.net, new_entry->address.node));
                   1446:        }
                   1447: #endif /* NBP_DEBUG */
                   1448: 
                   1449:        nbp_add_multicast(&new_entry->zone, ifID);
                   1450:        return (0);
                   1451: } /* nbp_new_nve_entry */
                   1452: 
                   1453: void nbp_delete_entry (nve_entry)
                   1454:      nve_entry_t       *nve_entry;
                   1455: {
                   1456:        TAILQ_REMOVE(&name_registry, nve_entry, nve_link);
                   1457:        gbuf_freem(nve_entry->tag);
                   1458:        at_state.flags |= AT_ST_NBP_CHANGED;
                   1459: }
                   1460: 
                   1461: /* Registration of an NBP entity in multihoming mode, from AIOCNBPREG
                   1462:    in at.c */
                   1463: int nbp_mh_reg(nbpP)
                   1464:      at_nbp_reg_t *nbpP;
                   1465: {
                   1466:        nve_entry_t nve;
                   1467:        at_ifaddr_t *ifID = 0;
                   1468:        int registered = 0;
                   1469:        int finished = FALSE;
                   1470: 
                   1471:        if (nbp_fillin_nve(&nbpP->name, &nve) != 0) {
                   1472:                /* bad tuple... */
                   1473:                dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                   1474:                        ("nbp_mh_reg: bad tuple\n"));
                   1475:                return(EINVAL);
                   1476:        }
                   1477:        nve.address = nbpP->addr;
                   1478:        nve.ddptype = nbpP->ddptype;
                   1479: 
                   1480:        if (DEFAULT_ZONE(&nbpP->name.zone)) {
                   1481:          /* multihoming mode with the default zone specified */
                   1482: 
                   1483:                /* now find the matching interfaces */
                   1484:                TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
                   1485:                        if (nbpP->addr.net || nbpP->addr.node) {
                   1486:                                /* if address is specified */
                   1487:                                if ((nbpP->addr.net != ifID->ifThisNode.s_net ||
                   1488:                                     nbpP->addr.node != ifID->ifThisNode.s_node)) 
                   1489:                                        continue;
                   1490:                                else
                   1491:                                        /* the address was specified, and 
                   1492:                                           we found the matching interface */
                   1493:                                        finished = TRUE;
                   1494:                        } else {
                   1495:                                /* address is not specified, so fill in
                   1496:                                   the address for the interface */
                   1497:                                nve.address.net = ifID->ifThisNode.s_net;
                   1498:                                nve.address.node = ifID->ifThisNode.s_node;
                   1499:                        }
                   1500:                        nve.zone = ifID->ifZoneName;
                   1501:                        nve.zone_hash = nbp_strhash(&nve.zone);
                   1502:                        if (nbp_find_nve(&nve)) 
                   1503:                                continue;
                   1504:                        if (nbp_new_nve_entry(&nve, ifID) == 0) 
                   1505:                                registered++;
                   1506:                }
                   1507:                if (registered && !nbpP->addr.net && !nbpP->addr.node) {
                   1508:                        nbpP->addr.net = ifID_home->ifThisNode.s_net;
                   1509:                        nbpP->addr.node = ifID_home->ifThisNode.s_node;
                   1510:                }
                   1511:        } else {
                   1512:                /* multihoming mode with a specific zone specified */
                   1513:                /* see which segments (interfaces) are seeded for this zone */
                   1514:                int zno;
                   1515:                char ifs_in_zone[IF_TOTAL_MAX];
                   1516:                if (!(zno = zt_find_zname(&nve.zone))) {
                   1517:                        dPrintf(D_M_NBP_LOW, D_L_WARNING, 
                   1518:                                ("nbp_mh_reg: didn't find zone name\n"));
                   1519:                        return(EINVAL);
                   1520:                }
                   1521:                getIfUsage(zno-1, ifs_in_zone);
                   1522: 
                   1523:                /* now find the first matching interface */
                   1524:                TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
                   1525:                        if (!ifs_in_zone[ifID->ifPort]) 
                   1526:                                        /* zone doesn't match */
                   1527:                                continue;
                   1528:                        else
                   1529:                                /* the zone matches, so unless the 
                   1530:                                   address is specified and doesn't 
                   1531:                                   match, we only need to do this once */
                   1532:                                finished = TRUE;
                   1533: 
                   1534:                        if (nbpP->addr.net || nbpP->addr.node) {
                   1535:                            /* address is specified */
                   1536:                            finished = FALSE;
                   1537:                            if ((nbpP->addr.net != ifID->ifThisNode.s_net ||
                   1538:                                 nbpP->addr.node != ifID->ifThisNode.s_node)) 
                   1539:                                continue;
                   1540:                            else
                   1541:                                /* the address was specified, and 
                   1542:                                   we found the matching interface */
                   1543:                                finished = TRUE;
                   1544:                        } else {
                   1545:                                /* address is not specified, so fill in
                   1546:                                   the address for the interface */
                   1547:                                nve.address.net = ifID->ifThisNode.s_net;
                   1548:                                nve.address.node = ifID->ifThisNode.s_node;
                   1549:                        }
                   1550:                        if (nbp_find_nve(&nve)) 
                   1551:                                continue;
                   1552:                        if (nbp_new_nve_entry(&nve, ifID) == 0)
                   1553:                                registered++;
                   1554:                }
                   1555:                if (registered && !nbpP->addr.net && !nbpP->addr.node) {
                   1556:                        nbpP->addr.net = ifID->ifThisNode.s_net;
                   1557:                        nbpP->addr.node = ifID->ifThisNode.s_node;
                   1558:                }
                   1559:        }
                   1560:        nbpP->unique_nbp_id = (registered > 1)? 0: nve.unique_nbp_id;
                   1561: 
                   1562:        if (registered)
                   1563:                return(0);
                   1564:        else
                   1565:                return(EADDRNOTAVAIL);
                   1566: 
                   1567: } /* nbp_mh_reg */

unix.superglobalmegacorp.com

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