|
|
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.