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