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