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