Annotation of XNU/bsd/netat/ddp_rtmptable.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:  *
                     24:  *            RTMP & ZIP routing tables access routines
                     25:  *
                     26:  * This code implement b-tree search and manipulation of
                     27:  * of the RTMP routing table and ZIP zone table.
                     28:  *
                     29:  * The RTMP routing table is a data block divided in several routing
                     30:  * entries sorted during insertion in a b-tree form. We use a table and
                     31:  * not dynamically allocated entries because it allow us to scan the whole
                     32:  * table when RTMP packets are generated. The routing table entries are sorted
                     33:  * by there NetStop value (because non extended nets have a NetStart value of
                     34:  * zero. From any point in the tree, the left side contains Network ranges
                     35:  * smaller or equal to the current Node, and the right tree points to higher
                     36:  * values network ranges. 
                     37:  *
                     38:  *
                     39:  * 0.01 3/16/94 LD     Creation
                     40:  *    Modified for MP, 1996 by Tuyen Nguyen
                     41:  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
                     42:  *
                     43:  *----------------------------------------------------------------------------
                     44:  *
                     45:  *      Copyright (c) 1994, 1996, 1997, 1998 Apple Computer, Inc.
                     46:  */
                     47: 
                     48: #include <sys/errno.h>
                     49: #include <sys/types.h>
                     50: #include <sys/param.h>
                     51: #include <machine/spl.h>
                     52: #include <sys/systm.h>
                     53: #include <sys/kernel.h>
                     54: #include <sys/proc.h>
                     55: #include <sys/filedesc.h>
                     56: #include <sys/fcntl.h>
                     57: #include <sys/mbuf.h>
                     58: #include <sys/ioctl.h>
                     59: #include <sys/malloc.h>
                     60: #include <sys/socket.h>
                     61: #include <sys/socketvar.h>
                     62: 
                     63: #include <net/if.h>
                     64: #include <net/if_types.h>
                     65: 
                     66: #include <netat/sysglue.h>
                     67: #include <netat/appletalk.h>
                     68: #include <netat/at_var.h>
                     69: #include <netat/lap.h>
                     70: #include <netat/ddp.h>
                     71: #include <netat/rtmp.h>
                     72: #include <netat/at_pcb.h>
                     73: #include <netat/zip.h>
                     74: #include <netat/routing_tables.h>
                     75: #include <netat/at_snmp.h>
                     76: #include <netat/debug.h>
                     77: #include <netat/at_config.h>
                     78: 
                     79: RT_entry *RT_table_freelist;   /* start of free entry list */
                     80: RT_entry RT_table_start;       /* start of the actual entry table */
                     81: RT_entry *RT_table;            /* the routing table */
                     82: ZT_entry *ZT_table;            /* the Zone Information Protocol table */
                     83: short  RT_maxentry;            /* Number of entry in RTMP table */
                     84: short  ZT_maxentry;            /* Number of entry in ZIP table */
                     85: 
                     86: char errstr[512];              /* used to display meaningfull router errors*/
                     87: 
                     88: extern at_ifaddr_t *ifID_table[];
                     89: extern at_ifaddr_t *ifID_home;
                     90: extern snmpStats_t     snmpStats;
                     91: extern atlock_t        ddpinp_lock;
                     92: 
                     93: short ErrorRTMPoverflow = 0;   /* flag if RTMP table is too small for this net */
                     94: short ErrorZIPoverflow  = 0;   /* flag if ZIP table is too small for this net */
                     95: 
                     96:        /* prototypes */
                     97: void getIfUsage( int,  char*);
                     98: 
                     99: /*
                    100:  * This a temporary function : just to display the router error 
                    101:  */
                    102: 
                    103: void RouterError(port, err_number)
                    104: short port, err_number;
                    105: 
                    106: {
                    107:        switch (err_number) {
                    108: 
                    109:        case ERTR_SEED_CONFLICT:
                    110:                dPrintf(D_M_RTMP, D_L_ERROR,
                    111:                         ("**** RTR Error on port# %d SEED_CONFLICT\n", port));
                    112:                break;
                    113:        
                    114:        case ERTR_CABLE_CONFLICT:
                    115:                dPrintf(D_M_RTMP, D_L_ERROR,
                    116:                        ("**** RTR Error on port# %d CABLE_CONFLICT\n", port));
                    117:                break;
                    118:        
                    119:        case ERTR_RTMP_BAD_VERSION:
                    120:                dPrintf(D_M_RTMP, D_L_ERROR,
                    121:                        ("**** RTR Error on port# %d RTMP_BAD_VERSION\n", port));
                    122:                break;
                    123: 
                    124:        case ERTR_CABLE_STARTUP:
                    125:                dPrintf(D_M_RTMP, D_L_ERROR,
                    126:                        ("**** RTR Error on port# %d RTMP_CABLE_STARTUP\n",
                    127:                         port));
                    128:                break;
                    129: 
                    130:        default:
                    131:                dPrintf(D_M_RTMP, D_L_ERROR,
                    132:                        ("**** RTR Error on port# %d WHAT IN THE WORLD IS THIS ONE? code=%d\n",
                    133:                        port, err_number));
                    134:                break;
                    135:        }
                    136:        dPrintf(D_M_RTMP, D_L_ERROR, ("Explanation: %s\n", errstr));
                    137: }
                    138:        
                    139: 
                    140: /*
                    141:  * this function just look for a NetNumber in the routing table,
                    142:  * no check is done for the validity of the entry
                    143:  */
                    144: 
                    145: RT_entry *rt_blookup (NetNumber)
                    146: at_net_al NetNumber;
                    147: {
                    148: 
                    149:        RT_entry *ptree = &RT_table_start;
                    150:        at_net_al LowEnd;
                    151:        register unsigned int s;
                    152: /*
                    153:        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Lookup for Net=%d\n",
                    154:                 "rt_blookup", NetNumber));
                    155: */     
                    156:        ATDISABLE(s, ddpinp_lock);
                    157:        while (ptree) {
                    158: 
                    159:                if (NetNumber > ptree->NetStop) {
                    160: /*
                    161:                        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Go Right from  #%d\n",
                    162:                                 "rt_blookup", ptree->NextIRNet));
                    163: */
                    164:                        ptree = ptree->right;
                    165:                        continue;
                    166:                }
                    167:                else {
                    168:                   if (ptree->NetStart) 
                    169:                        LowEnd = ptree->NetStart;
                    170:                   else
                    171:                        LowEnd = ptree->NetStop;
                    172: 
                    173:                   if (NetNumber < LowEnd ) {
                    174: /*
                    175:                        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Go Left from  #%d\n",
                    176:                                 "rt_blookup", ptree->NextIRNet));
                    177: */
                    178:                        ptree = ptree->left;
                    179:                        continue;
                    180:                   }
                    181:                   ATENABLE(s, ddpinp_lock);
                    182:                   
                    183:                   /* we're in the range (either extended or not)
                    184:                    * return the entry found.
                    185:                    */
                    186: 
                    187: /*                     dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : found %04d-%04d Port=%d State=0x%x\n",
                    188:                                "rt_blookup", ptree->NetStart, ptree->NetStop, ptree->NetPort,
                    189:                                ptree->EntryState));
                    190: */
                    191: 
                    192:                   return (ptree);
                    193:                }       
                    194:        }
                    195:        ATENABLE(s, ddpinp_lock);
                    196: 
                    197:        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : %04d : NOT FOUND\n",
                    198:                 "rt_blookup", NetNumber));
                    199:        return ((RT_entry *)NULL);
                    200: }
                    201: 
                    202: 
                    203: /* Routing table btree insert routine
                    204:  *  Uses a RT_entry parameter as the input, the insert is sorted in
                    205:  *  the tree on the NetStop field. Provision is made for non extented
                    206:  *  net (ie NetStart = 0).   
                    207:  *  The function returns the element where the new entry was inserted, or
                    208:  *  NULL if the insert didn't work. (In this cas there is a problem with
                    209:  *  the tree coherency...
                    210:  *  
                    211:  */
                    212: 
                    213: 
                    214: RT_entry *rt_binsert (NewEntry)
                    215: RT_entry *NewEntry;
                    216: {
                    217:        RT_entry *ptree = &RT_table_start;
                    218: 
                    219:        register at_net_al NetStart = NewEntry->NetStart;
                    220:        register at_net_al NetStop  = NewEntry->NetStop;
                    221: 
                    222:        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("rt_binsert: for Net %d-%d state=x%x NextIR %d:%d\n",
                    223:                 NetStart, NetStop, NewEntry->EntryState,NewEntry->NextIRNet, NewEntry->NextIRNode));
                    224: 
                    225:        if (ptree == (RT_entry *)NULL) {
                    226:                *ptree = *NewEntry;
                    227:                at_state.flags |= AT_ST_RT_CHANGED;
                    228:                return (NewEntry);
                    229:        }
                    230:        
                    231: 
                    232:        while (ptree) {
                    233: 
                    234:                if (NetStop > ptree->NetStop) { /* walk the right sub-tree */
                    235:                        if (ptree->right)
                    236:                                ptree = ptree->right;
                    237:                        else {
                    238:                                ptree->right = NewEntry;
                    239:                                at_state.flags |= AT_ST_RT_CHANGED;
                    240:                                return (ptree);
                    241:                        }
                    242:                }
                    243:                else { /* walk the left sub-tree */
                    244:                        if (ptree->left) 
                    245:                                ptree = ptree->left;
                    246:                        else {
                    247:                                ptree->left = NewEntry;
                    248:                                at_state.flags |= AT_ST_RT_CHANGED;
                    249:                                return (ptree);
                    250:                        }
                    251:                }
                    252: 
                    253:        }       
                    254: 
                    255:        dPrintf(D_M_RTMP, D_L_WARNING, ("%s : ERROR NOT INSERTED Net %d-%d\n",
                    256:                 "rt_binsert", NetStart, NetStop));
                    257:        return ((RT_entry *)NULL);
                    258: }
                    259: 
                    260: RT_entry *rt_insert(NStop, NStart, NxNet, NxNode, NtDist, NtPort, EntS) 
                    261:      at_net_al NStop, NStart, NxNet;
                    262:      at_node NxNode;
                    263:      u_char NtDist, NtPort, EntS;
                    264: {
                    265:     RT_entry *New; 
                    266:     if ((New = RT_table_freelist)) {
                    267:        RT_table_freelist = RT_table_freelist->right; 
                    268:     } else 
                    269:        return ((RT_entry *)NULL);
                    270:     New->right = NULL; 
                    271:     New->NetStop = NStop; 
                    272:     New->NetStart = NStart; 
                    273:     New->NextIRNet = NxNet; 
                    274:     New->NextIRNode = NxNode; 
                    275:     New->NetDist = NtDist; 
                    276:     New->NetPort = NtPort; 
                    277:     New->EntryState = EntS; 
                    278:     bzero(New->ZoneBitMap, sizeof(New->ZoneBitMap)); 
                    279:        at_state.flags |= AT_ST_RT_CHANGED; 
                    280:        return(rt_binsert(New)); 
                    281: }
                    282: 
                    283: /*
                    284:        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : %04d : NOT FOUND\n",
                    285:                 "rt_blookup", NetNumber));
                    286:  * Routing table btree deletion routine
                    287:  *
                    288:  */
                    289: 
                    290: RT_entry *rt_bdelete (NetStop, NetStart)
                    291:      at_net_al NetStop, NetStart;
                    292: {
                    293: 
                    294:        RT_entry *rt_found, *pprevious, *pnext, *pnextl, *psub;
                    295:        at_net_al LowEnd;
                    296: 
                    297:        rt_found = &RT_table_start;
                    298: 
                    299:        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Delete %d-%d\n",
                    300:                 "rt_bdelete", NetStart, NetStop));
                    301: 
                    302:        while (rt_found) {
                    303: 
                    304:                if (NetStop > rt_found->NetStop) {
                    305:                        pprevious = rt_found;
                    306:                        rt_found = rt_found->right;
                    307:                        continue;
                    308:                }
                    309:                else {
                    310:                
                    311:                   /* non extended nets cases */
                    312: 
                    313:                   if (rt_found->NetStart) 
                    314:                        LowEnd = rt_found->NetStart;
                    315:                   else
                    316:                        LowEnd = rt_found->NetStop;
                    317: 
                    318:                  if (NetStop < LowEnd) {
                    319:                        pprevious = rt_found;
                    320:                        rt_found = rt_found->left;
                    321:                        continue;
                    322:                   }
                    323:                   
                    324:                   /* we're in the range (either extended or not)
                    325:                    * return the entry found.
                    326:                    */
                    327: 
                    328:                   break;
                    329:                }       
                    330:        }
                    331: 
                    332:        dPrintf(D_M_RTMP, D_L_ROUTING, ("%s : Delete %d-%d found to delete %d-%d\n",
                    333:                 "rt_bdelete", NetStart, NetStop, rt_found->NetStart,rt_found->NetStop));
                    334: 
                    335:        if (rt_found) {
                    336: 
                    337: 
                    338: 
                    339:                   /* we found the entry, now reorg the sub-trees
                    340:                    * spanning from our node.
                    341:                    */
                    342: 
                    343:                    if ((pnext = rt_found->right)) {
                    344: 
                    345:                                /* Tree pruning: take the left branch of the current
                    346:                                 * node and place it at the lowest left branch
                    347:                                 * of the current right branch 
                    348:                                 */
                    349: 
                    350:                                psub = pnext;
                    351: 
                    352:                                /* walk the Right/Left sub tree from current node */
                    353: 
                    354:                                while ((pnextl = psub->left))
                    355:                                        psub = pnextl;  
                    356:                                
                    357:                                /* plug the old left tree to the new ->Right leftmost node */   
                    358:                                
                    359:                                psub->left = rt_found->left;
                    360:                                                
                    361: 
                    362:                    } else {     /* only left sub-tree, simple case */
                    363: 
                    364:                                pnext = rt_found->left;
                    365:                    }
                    366:                        
                    367:                        /* Now, plug the current node sub tree to the good pointer of 
                    368:              * our parent node.
                    369:              */
                    370: 
                    371: 
                    372:                        if (pprevious->left == rt_found)
                    373:                                pprevious->left = pnext;
                    374:                        else
                    375:                                pprevious->right = pnext;       
                    376: 
                    377:                        /* clean-up entry and add to the free-list */
                    378: 
                    379:                        at_state.flags |= AT_ST_RT_CHANGED;
                    380:                        return(rt_found);
                    381:        }
                    382: 
                    383:        else { /* Trying to delete something that doesn't exist? */
                    384: 
                    385:                dPrintf(D_M_RTMP, D_L_WARNING, ("%s : %d NOT Removed\n",
                    386:                        "rt_bdelete", NetStop));
                    387: 
                    388:                return ((RT_entry *)NULL);
                    389:        }
                    390: 
                    391:                                
                    392: }
                    393:                                        
                    394: 
                    395: RT_entry *rt_sortedshow(parent)
                    396: RT_entry *parent;
                    397: {
                    398:        RT_entry *me;
                    399:        
                    400:        me = parent;
                    401: 
                    402:        if (parent == NULL) {
                    403:                me = &RT_table_start;
                    404:                while (me) 
                    405:                        if (me->left) {
                    406:                                parent = me;
                    407:                                me = me->left;
                    408:                        }
                    409: /*             parent = parent->parent; */
                    410:        }
                    411:        return (parent);
                    412: }
                    413: 
                    414: /*
                    415:  * debug only: display the contents of the routing table
                    416:  */
                    417: 
                    418: void rt_show ()
                    419: {
                    420:        RT_entry *ptree;
                    421:        int i=0;
                    422: 
                    423:        ptree = &RT_table[0];
                    424: 
                    425:        while (ptree && i < 600 ) {
                    426:                if (ptree->NetStop) { 
                    427:                        dPrintf(D_M_RTMP_LOW, D_L_VERBOSE,
                    428:                                ("%4d-%4d IR=%d:%d Dist=%d\n",
                    429:                                ptree->NetStop, ptree->NetStart, ptree->NextIRNet,
                    430:                                ptree->NextIRNode, (short)ptree->NetDist));
                    431:                } else {
                    432:                        dPrintf(D_M_RTMP_LOW, D_L_VERBOSE,
                    433:                                ("%04d : * FREE ENTRY\n", i));
                    434:                }
                    435:                ptree++;
                    436:        i++;
                    437:        }
                    438: }
                    439: 
                    440: /*
                    441:  * prepare the indexing of the free entries in the RTMP table
                    442:  */
                    443: 
                    444: rt_table_init()
                    445: {
                    446:        short i;
                    447: 
                    448:        if ((RT_table = (RT_entry *)_MALLOC(sizeof(RT_entry)*RT_maxentry,
                    449:                                            M_RTABLE, M_NOWAIT)) == NULL) {
                    450:                dPrintf(D_M_RTMP, D_L_WARNING, 
                    451:                        ("rtmptable: Can't allocate RT_table\n"));
                    452:                return (ENOMEM);
                    453:        }
                    454:        if ((ZT_table = (ZT_entry *)_MALLOC(sizeof(ZT_entry)*ZT_maxentry,
                    455:                                            M_RTABLE, M_NOWAIT)) == NULL) {
                    456:                dPrintf(D_M_RTMP, D_L_WARNING, 
                    457:                        ("rtmptable: Can't allocate ZT_table\n"));
                    458:                return (ENOMEM);
                    459:        }
                    460:        dPrintf(D_M_RTMP, D_L_STARTUP, ("rt_table_init called\n"));
                    461:        bzero(&RT_table[0], sizeof(RT_entry)* RT_maxentry);
                    462:        for (i= 1 ; i < RT_maxentry ; i++) {
                    463:                (&RT_table[i-1])->right = &RT_table[i];
                    464:        }
                    465:        RT_table_freelist = &RT_table[0];
                    466: 
                    467:        at_state.flags |= AT_ST_RT_CHANGED;
                    468:        at_state.flags |= AT_ST_ZT_CHANGED;
                    469:        bzero(&RT_table_start, sizeof(RT_entry));
                    470: 
                    471:        /* also clean up the ZIP table */
                    472: 
                    473:        bzero(&ZT_table[0], sizeof(ZT_entry)* ZT_maxentry);
                    474:        ErrorRTMPoverflow = 0;
                    475:        ErrorZIPoverflow = 0;
                    476:        return(0);
                    477: }
                    478: 
                    479: /* 
                    480:  * zt_add_zone: add a zone name in the zone table.
                    481:  */
                    482: 
                    483: zt_add_zone(name, length)
                    484: char *name;
                    485: short length;
                    486: {
                    487:        at_nvestr_t zname;
                    488:        bcopy(name, &zname.str, length);
                    489:        zname.len = length;
                    490:        return (zt_add_zonename(&zname));
                    491: }
                    492: 
                    493: /* 
                    494:  * zt_add_zonename: add a zone name in the zone table.
                    495:  */
                    496: 
                    497: int zt_add_zonename(zname)
                    498: at_nvestr_t *zname;
                    499: {
                    500:        register short res,i;
                    501:        register unsigned int s;
                    502: 
                    503:        if (res = zt_find_zname(zname))
                    504:                return(res);
                    505: 
                    506:        ATDISABLE(s, ddpinp_lock);
                    507:        for (i = 0; i < ZT_maxentry ; i++) {
                    508:                if (ZT_table[i].ZoneCount == 0 && ZT_table[i].Zone.len == 0) {/* free entry */
                    509:                        ZT_table[i].Zone = *zname;
                    510:                        dPrintf(D_M_RTMP, D_L_VERBOSE, ("zt_add_zonename: zone #%d %s len=%d\n",
                    511:                                i, ZT_table[i].Zone.str, ZT_table[i].Zone.len));
                    512:                        at_state.flags |= AT_ST_ZT_CHANGED;
                    513:                        ATENABLE(s, ddpinp_lock);
                    514:                        return(i+1);
                    515:                }
                    516:        }
                    517:        ATENABLE(s, ddpinp_lock);
                    518:        /* table full... */
                    519:        return (ZT_MAXEDOUT);
                    520: }
                    521: 
                    522: /* Adjust zone counts for a removed network entry.
                    523:  * If the ZoneCount of a zone reaches zero, delete the zone from the zone table
                    524:  */
                    525: void zt_remove_zones(zmap)
                    526: u_char *zmap;
                    527: {
                    528: 
                    529:        register        u_short i,j, Index;
                    530: 
                    531:        for (i=0; i< ZT_BYTES ; i++) {
                    532: 
                    533:                if (zmap[i]) {
                    534:                        for (j=0; j < 8 ; j++)
                    535:                                if ((zmap[i] << j) & 0x80) {
                    536:                                        Index = i*8 + j;        /* get the index in ZT */
                    537:                                                /* 1-23-97 this routine caused a crash once, presumably
                    538:                                               zmap bits beyond ZT_table size got set somehow.
                    539:                            prevent that here
                    540:                                                 */
                    541:                                        if (Index >= ZT_maxentry) {
                    542:                                                dPrintf(D_M_RTMP, D_L_ERROR,
                    543:                                                        ("zt_remove_zones: index (%d) GT ZT_maxentry (%d) (zmap:%d)\n",
                    544:                                                        Index,ZT_maxentry,i));
                    545:                                                return;
                    546:                                        }
                    547:                                        dPrintf(D_M_RTMP, D_L_VERBOSE,
                    548:                                                ("zt_remove_zones: zone #%d %s was=%d\n", Index,
                    549:                                                ZT_table[Index].Zone.str, ZT_table[Index].ZoneCount));
                    550:                                        if (ZT_table[Index].ZoneCount > 0) 
                    551:                                                ZT_table[Index].ZoneCount--;
                    552:                                        if (ZT_table[Index].ZoneCount == 0)
                    553:                                                        ZT_table[Index].Zone.len = 0;
                    554:                                        at_state.flags |= AT_ST_ZT_CHANGED;
                    555:                                }
                    556:                }
                    557:        }
                    558: }
                    559: 
                    560: 
                    561: 
                    562: /*
                    563:  * zt_compute_hash: compute hash index from the zone name string
                    564:  */
                    565: 
                    566: short zt_compute_hash(zname)
                    567: at_nvestr_t *zname;
                    568: {
                    569:        register u_short checksum=0, i;
                    570:        register char c1;
                    571: 
                    572:        /* apply the upper name + DDP checksum algorithm */
                    573: 
                    574:        for (i= 0 ; i < zname->len; i++) {
                    575: 
                    576:                        /* upperize the character */
                    577: 
                    578:                        c1 = zname->str[i];
                    579:             if (c1 >= 'a' && c1 <= 'z')
                    580:                    c1 += 'A' - 'a';
                    581:             if (c1 & 0x80)
                    582:                 c1 = upshift8(c1);
                    583: 
                    584:                        /* DDP Checksum */
                    585: 
                    586:                        checksum += c1;
                    587:                        checksum = ((checksum & 0x8000) ?
                    588:                                (checksum << 1 | 1) : (checksum << 1));
                    589:        }
                    590: 
                    591:        dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("zt_comphash: value computed for zone=%s h=%d\n",
                    592:                zname->str, checksum));
                    593: 
                    594:        if (checksum)
                    595:                return (checksum);
                    596:        else
                    597:                return (0xffff);
                    598: 
                    599: }
                    600: 
                    601: /* 
                    602:  * zt_upper_zname: translate the name string into uppercase
                    603:  */
                    604: 
                    605: void zt_upper_zname(zname)
                    606: at_nvestr_t *zname;
                    607: {
                    608:        register short i;
                    609:        register char c1;
                    610: 
                    611:        for (i= 0 ; i < zname->len; i++) {
                    612: 
                    613:                        c1 = zname->str[i];
                    614:             if (c1 >= 'a' && c1 <= 'z')
                    615:                    c1 += 'A' - 'a';
                    616:             if (c1 & 0x80)
                    617:                 c1 = upshift8(c1);
                    618: 
                    619:                        zname->str[i] = c1;
                    620:        }
                    621: }
                    622: 
                    623: /*
                    624:  * zt_get_zmcast: calcularte the zone multicast address for a
                    625:  *                    given zone name. 
                    626:  *                    Returns the result in "buffer"
                    627:  */
                    628: 
                    629: zt_get_zmcast(ifID, zname, buffer)
                    630:      at_ifaddr_t *ifID;                /* we want to know the media type */
                    631:      at_nvestr_t *zname;       /* source name for multicast address */
                    632:      char *buffer;             /* resulting Zone Multicast address */
                    633: {
                    634:        u_short h;
                    635: 
                    636:        h = zt_compute_hash(zname);
                    637: 
                    638: /*
                    639:  * Find a nice way to decide if it is TokenRing or Ethernet for
                    640:  * the Multicast address computation....
                    641:  */
                    642: 
                    643:        if (ifID->aa_ifp->if_type != IFT_ISO88025) { /* token ring */
                    644: 
                    645:                /* Ethernet case */
                    646: 
                    647:                buffer[0] = 0x09;
                    648:                buffer[1] = 0x00;
                    649:                buffer[2] = 0x07;
                    650:                                /* no router, use cable multicast */
                    651:                if (MULTIHOME_MODE && ifID->ifRouterState == NO_ROUTER ) {
                    652:                        buffer[3] = buffer[4] = buffer[5] =  0xff;
                    653:                }
                    654:                else {
                    655:                        buffer[3] = 0x00;
                    656:                        buffer[4] = 0x00;
                    657:                        buffer[5] = h % 0xFD;
                    658:                }
                    659:                dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("zt_get_multi: computed for h=%d %x %x\n",
                    660:                                h, *(u_int *)&buffer[0], *(u_short *)&buffer[4]));
                    661:  
                    662:                return(6); /* returns Multicast address length */
                    663: 
                    664:        }
                    665:        else {
                    666:                 /* assume it is token ring: note for the magic number computation,
                    667:                  * first see Inside Mac Page 3-10, there is 20 multicast addresses
                    668:                  * for TLAP, and they are from 0xC000 0000 0008 00 to 0xC000 0200 0000 00
                    669:                  */
                    670:                buffer[0] = 0xC0;
                    671:                buffer[1] = 0x00;
                    672:                *(u_int *)&buffer[2] = 1 << ((h % 19) + 11);
                    673:                dPrintf(D_M_RTMP, D_L_WARNING,("zt_get_multi: BROAD not found forr h=%d \n",
                    674:                         h));
                    675:                return(6);
                    676:        }
                    677: 
                    678: 
                    679: 
                    680: }
                    681: 
                    682: /*
                    683:  * zt_ent_zindex: return the first zone index found in the zone map
                    684:  * return the entry number+1 in the Zone Table, or zero if not found
                    685:  */
                    686: 
                    687: int zt_ent_zindex(zmap)
                    688: u_char *zmap;
                    689: {
                    690:        u_short i,j;
                    691: 
                    692: 
                    693:        for (i = 0 ; i < ZT_BYTES ; i++)
                    694: 
                    695:                if (zmap[i]) 
                    696:                        for (j = 0 ; j < 8 ; j++)
                    697:                                if ((zmap[i] << j) & 0x80)
                    698:                                        return (8*i + j +1);
                    699: 
                    700:        return (0);
                    701: }
                    702: /*
                    703:  * zt_ent_zcount: count the number of actives zone for a routing entry
                    704:  */
                    705: 
                    706: zt_ent_zcount(ent)
                    707: RT_entry *ent;
                    708: {
                    709:        register u_char *zmap;
                    710:        register u_short i,j;
                    711:        register int       zone_count = 0 ;
                    712:        register unsigned int s;
                    713: 
                    714:        ATDISABLE(s, ddpinp_lock);
                    715: 
                    716:        if (!RT_ALL_ZONES_KNOWN(ent)) {
                    717:                        ATENABLE(s, ddpinp_lock);
                    718:                        return (0);
                    719:        }
                    720:        zmap = ent->ZoneBitMap;
                    721: 
                    722:        for (i = 0 ; i < ZT_BYTES ; i++) {
                    723: 
                    724:                if (*zmap) 
                    725: 
                    726:                        for (j = 0 ; j < 8 ; j++)
                    727:                                if ((*zmap << j) & 0x80)
                    728:                                        zone_count++;
                    729:                zmap++;
                    730:        }
                    731: 
                    732:        ATENABLE(s, ddpinp_lock);
                    733:        return (zone_count);
                    734: }
                    735: 
                    736: /*
                    737:  * zt_find_zname: match a zone name in the zone table and return the entry if found
                    738:  */
                    739: zt_find_zname(zname)
                    740: at_nvestr_t *zname;
                    741: {
                    742:        register short i, j, found;
                    743:        register char c1, c2;
                    744:        register unsigned int s;
                    745: 
                    746: 
                    747:        if (!zname->len)
                    748:                return(0);
                    749: 
                    750:        ATDISABLE(s, ddpinp_lock);
                    751:        for (i = 0 ; i < ZT_maxentry ; i++) {
                    752:                        if (!ZT_table[i].ZoneCount || zname->len != ZT_table[i].Zone.len)
                    753:                                        continue;
                    754: 
                    755:                        found = 1; /* did we get the right one? */
                    756: 
                    757:                        for (j = 0 ; j < zname->len ; j++) {
                    758:                    c1 = zname->str[j];
                    759:                 c2 = ZT_table[i].Zone.str[j];
                    760:                 if (c1 >= 'a' && c1 <= 'z')
                    761:                         c1 += 'A' - 'a';
                    762:                 if (c2 >= 'a' && c2 <= 'z')
                    763:                         c2 += 'A' - 'a';
                    764:                 if (c1 & 0x80)
                    765:                         c1 = upshift8(c1);
                    766:                 if (c2 & 0x80)
                    767:                         c2 = upshift8(c2);
                    768:                 if (c1 != c2) {
                    769:                         found = 0;
                    770:                                                break;
                    771:                                }
                    772:                        }
                    773: 
                    774:                        if (found) {
                    775:                                ATENABLE(s, ddpinp_lock);
                    776:                                return (i+1);
                    777:                        }
                    778:        }
                    779: 
                    780:        ATENABLE(s, ddpinp_lock);
                    781:        return(0);
                    782: }
                    783: 
                    784:        
                    785: /*
                    786:  * zt_set_zmap: set a bit for the corresponding zone map in an entry bitmap
                    787:  */
                    788: void zt_set_zmap(znum, zmap)
                    789:      u_short znum;
                    790:      char *zmap;
                    791: {
                    792:        register u_short num = znum -1;
                    793:        register unsigned int s;
                    794: 
                    795:        ATDISABLE(s, ddpinp_lock);
                    796:        if (!(zmap[num >> 3] & 0x80 >> (num % 8))) {
                    797:                zmap[num >> 3] |= 0x80 >> (num % 8);
                    798:                ZT_table[num].ZoneCount++;
                    799:        }
                    800:        ATENABLE(s, ddpinp_lock);
                    801: }
                    802: 
                    803: 
                    804: /*
                    805:  * zt_clr_zmap: clear a bit for the corresponding zone map in an entry bitmap
                    806:  */
                    807: void zt_clr_zmap(znum, zmap)
                    808:      u_short znum;
                    809:      char *zmap;
                    810: {
                    811:        register u_short num = znum -1;
                    812:        register unsigned int s;
                    813: 
                    814:        ATDISABLE(s, ddpinp_lock);
                    815:        if (zmap[num >> 3] & 0x80 >> (num % 8)) {
                    816:                zmap[num >> 3] ^= 0x80 >> (num % 8);
                    817:                ZT_table[num].ZoneCount--;
                    818:        }
                    819:        ATENABLE(s, ddpinp_lock);
                    820: }
                    821: 
                    822: 
                    823: /*
                    824:  * routing_needed : 
                    825:  * This function performs the actual lookup and forward of packets
                    826:  * send to the box for routing.
                    827:  *
                    828:  * The destination network is looked up in our tables, and if we
                    829:  * know the next IR to send the packet to, we forward the packet
                    830:  * on the right port.
                    831:  *
                    832:  * If the destination is unknown, we simply dump the packet.
                    833:  */
                    834: 
                    835: void routing_needed(mp, ifID, bypass)
                    836:      gbuf_t   *mp;
                    837:      at_ifaddr_t *ifID;
                    838:      char bypass;      /* set by special socket handlers */
                    839: {
                    840: 
                    841:        register at_ddp_t *ddp;
                    842:        register int       msgsize;
                    843:        register RT_entry *Entry;
                    844:        register gbuf_t *tmp_m;
                    845: 
                    846:        /* first check the interface is up and forwarding */
                    847: 
                    848:        if (!ifID) {
                    849:                dPrintf(D_M_RTMP, D_L_WARNING, 
                    850:                        ("routing_needed: non valid IFID!\n"));
                    851:                gbuf_freel(mp);         
                    852:                return;
                    853:        }
                    854:        if ((ifID->ifRoutingState < PORT_ONLINE)) {
                    855:                dPrintf(D_M_RTMP, D_L_WARNING, 
                    856:                        ("routing_needed: port %d not online yet\n",
                    857:                         ifID->ifPort));
                    858:                gbuf_freel(mp);         
                    859:                return;
                    860:        }
                    861: 
                    862:        ddp = (at_ddp_t *)gbuf_rptr(mp);
                    863:        msgsize = DDPLEN_VALUE(ddp);
                    864:        for (tmp_m = gbuf_next(mp); tmp_m; tmp_m = gbuf_next(tmp_m))
                    865:                msgsize += DDPLEN_VALUE(((at_ddp_t *)gbuf_rptr(tmp_m)));
                    866:        
                    867:        if (ddp->hopcount++ > 15) {
                    868:                dPrintf(D_M_RTMP, D_L_WARNING,
                    869:                        ("routing_needed: drop packet for %d:%d, hopcount too high\n",
                    870:                        NET_VALUE(ddp->dst_net), ddp->dst_node));
                    871:                gbuf_freel(mp);
                    872:                snmpStats.dd_hopCount++;
                    873:                return; /* was return(1); */
                    874:        }
                    875: 
                    876:        if ((Entry = rt_blookup(NET_VALUE(ddp->dst_net)))) {
                    877:        
                    878:                dPrintf(D_M_RTMP_LOW, D_L_ROUTING,
                    879:                        ("routing_needed: FOUND for %d.%d p=%d to %d.%d \n",
                    880:                        NET_VALUE(ddp->dst_net), ddp->dst_node, ifID->ifPort,
                    881:                        Entry->NextIRNet, Entry->NextIRNode));
                    882: 
                    883:                /* somehow, come to that point... */
                    884: 
                    885:                ifID->ifStatistics.fwdPkts++;
                    886:                ifID->ifStatistics.fwdBytes += msgsize;
                    887: 
                    888:                if (Entry->NetDist)  /* net not directly connected */
                    889:                        ddp_router_output(mp, ifID_table[Entry->NetPort], AT_ADDR,
                    890:                                 Entry->NextIRNet, Entry->NextIRNode, 0);
                    891:                else {/* we are directly on this net */
                    892: 
                    893:                        /* we want to avoid duplicating broadcast packet on the same net,
                    894:                         * but special sockets handlers are ok to do that (mainly for
                    895:                         * for loopback purpose). So, if the "bypass" flag is set, we don't
                    896:                         * check for that test... [Problem was "movietalk"].
                    897:                         */
                    898: 
                    899:                        if (bypass || ifID_table[Entry->NetPort] != ifID) 
                    900:                                ddp_router_output(mp, ifID_table[Entry->NetPort], AT_ADDR,
                    901:                                 NET_VALUE(ddp->dst_net), ddp->dst_node, 0);
                    902:                        else {
                    903:                                dPrintf(D_M_RTMP, D_L_ROUTING,
                    904:                                        ("routing_needed: bad loopback for add %d.%d from port %d (%d.%d)\n",
                    905:                                         NET_VALUE(ddp->dst_net), ddp->dst_node, ifID->ifPort,
                    906:                                         NET_VALUE(ddp->src_net), ddp->src_node));
                    907:                                ifID->ifStatistics.droppedPkts++;
                    908:                                ifID->ifStatistics.droppedBytes += msgsize;
                    909: 
                    910:                                gbuf_freel(mp);
                    911:                                return; /* was return (2); */
                    912:                        }
                    913:  
                    914: 
                    915:                }
                    916:        }
                    917:        else {
                    918:                dPrintf(D_M_RTMP, D_L_ROUTING,
                    919:                        ("routing_needed: NOT FOUND for add %d.%d from port %d our %d.%d\n",
                    920:                         NET_VALUE(ddp->dst_net), ddp->dst_node, ifID->ifPort,
                    921:                         ifID_home->ifThisNode.s_net,
                    922:                         ifID_home->ifThisNode.s_node));
                    923: 
                    924:                ifID->ifStatistics.droppedPkts++;
                    925:                ifID->ifStatistics.droppedBytes += msgsize;
                    926:                snmpStats.dd_noRoutes++;
                    927: 
                    928:                gbuf_freel(mp);
                    929:                return; /* was return (2); */
                    930: 
                    931:        }
                    932:        /*      return(0); */
                    933: } /* routing_needed */
                    934: 
                    935: ZT_entryno *zt_getNextZone(first)
                    936:        int     first;  
                    937:        /* a call made with first = TRUE returns the first valid entry in
                    938:           the ZT_table, if first != TRUE, then then each call returns the
                    939:           next valid entry in the table. The next call after the last
                    940:           valid entry was read returns NULL
                    941:        */
                    942: {
                    943:        int             i;
                    944:        static int      idx=0;
                    945:        static ZT_entryno       zte;
                    946:        
                    947:        if (!ZT_table)
                    948:                return NULL;
                    949: 
                    950:        if (first)
                    951:                idx=0;
                    952: 
                    953:        for (i=idx; i<ZT_maxentry; i++) {
                    954:                if (ZT_table[i].ZoneCount)
                    955:                        break;
                    956:        }
                    957:        if (i<ZT_maxentry) {
                    958:                idx = i+1;
                    959:                zte.zt = ZT_table[i];
                    960:                zte.entryno = i;
                    961:                return(&zte);
                    962:        }
                    963:        else
                    964:                return(NULL);
                    965: }
                    966: 
                    967: RT_entry *rt_getNextRoute(first)
                    968:        int     first;  
                    969: 
                    970: /* a call made with first = TRUE returns the first valid entry in
                    971:    the RT_table, if first != TRUE, then then each call returns the
                    972:    next valid entry in the table. The next call after the last
                    973:    valid entry was read returns NULL
                    974: */
                    975: 
                    976: {
                    977:        int             i;
                    978:        static int      idx=0;
                    979:        
                    980:        if (!RT_table)
                    981:                return(NULL);
                    982: 
                    983:        if (first)
                    984:                idx=0;
                    985: 
                    986:        for (i=idx; i<RT_maxentry; i++) {
                    987:                if (RT_table[i].EntryState != RTE_STATE_UNUSED)
                    988:                        break;
                    989:        }
                    990:        if (i<RT_maxentry) {
                    991:                idx = i+1;
                    992:                return(&RT_table[i]);
                    993:        }
                    994:        else
                    995:                return(NULL);
                    996: }
                    997: 
                    998: 
                    999: getRtmpTableSize()
                   1000: {
                   1001:        register int i;
                   1002:        register RT_entry *rt;
                   1003:        static  int size=0;
                   1004: 
                   1005:        if(!(at_state.flags &AT_ST_RT_CHANGED))         
                   1006:                return(size);
                   1007: 
                   1008:        for (i=RT_maxentry,rt = &RT_table[RT_maxentry-1]; i; i--,rt--)
                   1009:                if (rt->EntryState != RTE_STATE_UNUSED) {
                   1010:                        size = i;
                   1011:                        return(i);
                   1012:                }
                   1013:        return(0);
                   1014: }
                   1015: 
                   1016: getZipTableSize()
                   1017: {
                   1018:        register int i;
                   1019:        register ZT_entry *zt;
                   1020:        static  int size=0;
                   1021: 
                   1022:        if (!(at_state.flags & AT_ST_ZT_CHANGED))
                   1023:                return(size);
                   1024: 
                   1025:        for (i=ZT_maxentry,zt = &ZT_table[ZT_maxentry-1]; i; i--,zt--)
                   1026:                if (zt->ZoneCount) {
                   1027:                        size = i;
                   1028:                        return(i);
                   1029:                }
                   1030:        return(0);
                   1031: }
                   1032: 
                   1033: getRtmpTable(d,s,c)
                   1034:      RT_entry  *d;             /* destination */
                   1035:      int       s;              /* starting entry */
                   1036:      int       c;              /* # entries to copy */
                   1037: {
                   1038:        register int i,n=0;
                   1039:        register RT_entry       *rt;
                   1040: 
                   1041:        for(i=s,rt=&RT_table[s]; i<RT_maxentry && n<c; rt++,i++)
                   1042:                if (rt->EntryState != RTE_STATE_UNUSED) {
                   1043:                        *d++ = *rt;
                   1044:                        n++;
                   1045:                }
                   1046: }
                   1047: 
                   1048: getZipTable(d,s,c)
                   1049:      ZT_entry  *d;             /* destination */
                   1050:      int       s;              /* starting entry */
                   1051:      int       c;              /* # entries to copy */
                   1052: {
                   1053: 
                   1054:        bcopy(&ZT_table[s], d, c*sizeof(ZT_entry));
                   1055: }
                   1056: 
                   1057: at_nvestr_t *getRTRLocalZone(ifz)
                   1058:      if_zone_t *ifz;
                   1059: {
                   1060:        char *zmap;
                   1061:        RT_entry        *route;
                   1062:        int i, j, index;
                   1063:        int  zcnt=0;            /* zone we're pointing to in the list */
                   1064:        char zonesChecked[ZT_BYTES];
                   1065:        at_ifaddr_t *ifID;
                   1066: 
                   1067:        if (ifz->ifzn.zone < 0) {
                   1068:                return((at_nvestr_t*)NULL);
                   1069:        }
                   1070:        bzero(zonesChecked,sizeof(zonesChecked));
                   1071:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
                   1072:                if (!(route = rt_blookup(ifID->ifThisNode.s_net))) {
                   1073:                        return((at_nvestr_t*)NULL);
                   1074:                }       
                   1075:                zmap=route->ZoneBitMap;
                   1076:                dPrintf(D_M_RTMP_LOW, D_L_USR1,
                   1077:                        ("getRTRLocal: i/f %s, net:%d\n",ifID->ifName, 
                   1078:                         ifID->ifThisNode.s_net));
                   1079:                for (i = 0 ; i < ZT_BYTES; i++) {
                   1080:                  if (zmap[i]) {
                   1081:                    for (j = 0; j < 8 ; j++)
                   1082:                      if (  (zmap[i]  & (0x80 >> j)) &&
                   1083:                            !(zonesChecked[i] & (0x80 >> j)) 
                   1084:                            ) {
                   1085:                        zonesChecked[i] |=  (0x80 >> j);
                   1086:                        if (ifz->ifzn.zone == zcnt) {
                   1087:                          index = i * 8 + j;
                   1088:                          getIfUsage(index,ifz->usage);
                   1089:                          ifz->ifzn.ifnve = ZT_table[index].Zone;
                   1090:                          dPrintf(D_M_RTMP_LOW, D_L_USR1,
                   1091:                                  ("getRTRLocal:zmap:%8x zcnt:%d usage:%8x\n",
                   1092:                                   *(int*)zmap,zcnt,*(int*)ifz->usage));
                   1093:                          ifz->index = index+1;
                   1094:                          return(&ZT_table[index].Zone);
                   1095:                        }
                   1096:                        zcnt++;
                   1097:                      }
                   1098:                  }
                   1099:                }
                   1100:        }
                   1101:        dPrintf(D_M_RTMP_LOW, D_L_USR1,
                   1102:                ("getRTRLocal: returning NULL last ent:%d net:%d zmap:%08x\n",
                   1103:                 (ifID ? ifID->ifPort : 0),
                   1104:                 (ifID ? ifID->ifThisNode.s_net : 0),*(int*)zmap));
                   1105:        ifz->ifzn.ifnve.len = 0;
                   1106:        return((at_nvestr_t*)NULL);
                   1107: } /* getRTRLocalZone */
                   1108: 
                   1109: void getIfUsage(zone, ifs_in_zone)
                   1110:      int zone;
                   1111:      char *ifs_in_zone;
                   1112: 
                   1113: /* sets a "1" in each element of the char array for each I/F in the
                   1114:    requested zone. The char array has a 1:1 correspondence with the
                   1115:    ifID_table. Zone is assumed to be valid and local, so if we're in
                   1116:    single port mode, we'll set the home port and thats it.
                   1117: */
                   1118: {
                   1119:        u_int   zmi;    /* zone map index for zone */
                   1120:        u_char  zmb;    /* zone map bit mask for zone */
                   1121:        RT_entry        *route;
                   1122:        int cnt=0;
                   1123:        at_ifaddr_t     *ifID;
                   1124: 
                   1125:        if (!MULTIPORT_MODE) {
                   1126:                ifs_in_zone[0] = 1;
                   1127:                return;
                   1128:        }
                   1129:        bzero(ifs_in_zone,IF_TOTAL_MAX);
                   1130:        zmi = zone>>3;
                   1131:        zmb = 0x80>>(zone % 8);
                   1132:        dPrintf(D_M_NBP_LOW, D_L_USR3, ("get_ifs znum:%d zmi%d zmb:%x\n",
                   1133:                zone, zmi, zmb));
                   1134:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
                   1135:                if (!(route = rt_blookup(ifID->ifThisNode.s_net)))
                   1136:                        return;
                   1137:                if (route->ZoneBitMap[zmi] & zmb) {
                   1138:                        dPrintf(D_M_NBP_LOW, D_L_USR3, ("zone in port %d \n",
                   1139:                                route->NetPort));
                   1140:                        ifs_in_zone[route->NetPort] = 1;
                   1141:                        cnt++;
                   1142:                }
                   1143:        }
                   1144:        return;
                   1145: } /* getIfUsage */

unix.superglobalmegacorp.com

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