]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/ddp_rtmptable.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / bsd / netat / ddp_rtmptable.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
d7e50217
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
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 * 0.01 3/16/94 LD Creation
43 * Modified for MP, 1996 by Tuyen Nguyen
44 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
45 *
46 *----------------------------------------------------------------------------
47 *
48 * Copyright (c) 1994, 1996, 1997, 1998 Apple Computer, Inc.
49 */
50
51#include <sys/errno.h>
52#include <sys/types.h>
53#include <sys/param.h>
54#include <machine/spl.h>
55#include <sys/systm.h>
56#include <sys/kernel.h>
57#include <sys/proc.h>
58#include <sys/filedesc.h>
59#include <sys/fcntl.h>
60#include <sys/mbuf.h>
61#include <sys/ioctl.h>
62#include <sys/malloc.h>
63#include <sys/socket.h>
64#include <sys/socketvar.h>
65
66#include <net/if.h>
67#include <net/if_types.h>
68
69#include <netat/sysglue.h>
70#include <netat/appletalk.h>
71#include <netat/at_var.h>
72#include <netat/ddp.h>
73#include <netat/rtmp.h>
74#include <netat/at_pcb.h>
75#include <netat/zip.h>
76#include <netat/routing_tables.h>
77#include <netat/at_snmp.h>
78#include <netat/debug.h>
79
80RT_entry *RT_table_freelist; /* start of free entry list */
81RT_entry RT_table_start; /* start of the actual entry table */
82RT_entry *RT_table; /* the routing table */
83ZT_entry *ZT_table; /* the Zone Information Protocol table */
84short RT_maxentry; /* Number of entry in RTMP table */
85short ZT_maxentry; /* Number of entry in ZIP table */
86
87char errstr[512]; /* used to display meaningfull router errors*/
88
89extern at_ifaddr_t *ifID_table[];
90extern at_ifaddr_t *ifID_home;
91extern snmpStats_t snmpStats;
92extern atlock_t ddpinp_lock;
93
94short ErrorRTMPoverflow = 0; /* flag if RTMP table is too small for this net */
95short ErrorZIPoverflow = 0; /* flag if ZIP table is too small for this net */
96
97 /* prototypes */
98void getIfUsage( int, at_ifnames_t *);
99
100/*
101 * This a temporary function : just to display the router error
102 */
103
104void RouterError(port, err_number)
105short 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
146RT_entry *rt_blookup (NetNumber)
147at_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
215RT_entry *rt_binsert (NewEntry)
216RT_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_state.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_state.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_state.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
261RT_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 } else
270 return ((RT_entry *)NULL);
271 New->right = NULL;
272 New->NetStop = NStop;
273 New->NetStart = NStart;
274 New->NextIRNet = NxNet;
275 New->NextIRNode = NxNode;
276 New->NetDist = NtDist;
277 New->NetPort = NtPort;
278 New->EntryState = EntS;
279 bzero(New->ZoneBitMap, sizeof(New->ZoneBitMap));
280 at_state.flags |= AT_ST_RT_CHANGED;
281 return(rt_binsert(New));
282}
283
284/*
285 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : %04d : NOT FOUND\n",
286 "rt_blookup", NetNumber));
287 * Routing table btree deletion routine
288 *
289 */
290
291RT_entry *rt_bdelete (NetStop, NetStart)
292 at_net_al NetStop, NetStart;
293{
294
295 RT_entry *rt_found, *pprevious, *pnext, *pnextl, *psub;
296 at_net_al LowEnd;
297
298 rt_found = &RT_table_start;
299
300 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Delete %d-%d\n",
301 "rt_bdelete", NetStart, NetStop));
302
303 while (rt_found) {
304
305 if (NetStop > rt_found->NetStop) {
306 pprevious = rt_found;
307 rt_found = rt_found->right;
308 continue;
309 }
310 else {
311
312 /* non extended nets cases */
313
314 if (rt_found->NetStart)
315 LowEnd = rt_found->NetStart;
316 else
317 LowEnd = rt_found->NetStop;
318
319 if (NetStop < LowEnd) {
320 pprevious = rt_found;
321 rt_found = rt_found->left;
322 continue;
323 }
324
325 /* we're in the range (either extended or not)
326 * return the entry found.
327 */
328
329 break;
330 }
331 }
332
333 dPrintf(D_M_RTMP, D_L_ROUTING, ("%s : Delete %d-%d found to delete %d-%d\n",
334 "rt_bdelete", NetStart, NetStop, rt_found->NetStart,rt_found->NetStop));
335
336 if (rt_found) {
337
338
339
340 /* we found the entry, now reorg the sub-trees
341 * spanning from our node.
342 */
343
344 if ((pnext = rt_found->right)) {
345
346 /* Tree pruning: take the left branch of the current
347 * node and place it at the lowest left branch
348 * of the current right branch
349 */
350
351 psub = pnext;
352
353 /* walk the Right/Left sub tree from current node */
354
355 while ((pnextl = psub->left))
356 psub = pnextl;
357
358 /* plug the old left tree to the new ->Right leftmost node */
359
360 psub->left = rt_found->left;
361
362
363 } else { /* only left sub-tree, simple case */
364
365 pnext = rt_found->left;
366 }
367
368 /* Now, plug the current node sub tree to the good pointer of
369 * our parent node.
370 */
371
372
373 if (pprevious->left == rt_found)
374 pprevious->left = pnext;
375 else
376 pprevious->right = pnext;
377
378 /* clean-up entry and add to the free-list */
379
380 at_state.flags |= AT_ST_RT_CHANGED;
381 return(rt_found);
382 }
383
384 else { /* Trying to delete something that doesn't exist? */
385
386 dPrintf(D_M_RTMP, D_L_WARNING, ("%s : %d NOT Removed\n",
387 "rt_bdelete", NetStop));
388
389 return ((RT_entry *)NULL);
390 }
391
392
393}
394
395
396RT_entry *rt_sortedshow(parent)
397RT_entry *parent;
398{
399 RT_entry *me;
400
401 me = parent;
402
403 if (parent == NULL) {
404 me = &RT_table_start;
405 while (me)
406 if (me->left) {
407 parent = me;
408 me = me->left;
409 }
410/* parent = parent->parent; */
411 }
412 return (parent);
413}
414
415/*
416 * debug only: display the contents of the routing table
417 */
418
419void rt_show ()
420{
421 RT_entry *ptree;
422 int i=0;
423
424 ptree = &RT_table[0];
425
426 while (ptree && i < 600 ) {
427 if (ptree->NetStop) {
428 dPrintf(D_M_RTMP_LOW, D_L_VERBOSE,
429 ("%4d-%4d IR=%d:%d Dist=%d\n",
430 ptree->NetStop, ptree->NetStart, ptree->NextIRNet,
431 ptree->NextIRNode, (short)ptree->NetDist));
432 } else {
433 dPrintf(D_M_RTMP_LOW, D_L_VERBOSE,
434 ("%04d : * FREE ENTRY\n", i));
435 }
436 ptree++;
437 i++;
438 }
439}
440
441/*
442 * prepare the indexing of the free entries in the RTMP table
443 */
444
445rt_table_init()
446{
447 short i;
448
449 if ((RT_table = (RT_entry *)_MALLOC(sizeof(RT_entry)*RT_maxentry,
450 M_RTABLE, M_WAITOK)) == NULL) {
451 dPrintf(D_M_RTMP, D_L_WARNING,
452 ("rtmptable: Can't allocate RT_table\n"));
453 return (ENOMEM);
454 }
455 if ((ZT_table = (ZT_entry *)_MALLOC(sizeof(ZT_entry)*ZT_maxentry,
456 M_RTABLE, M_WAITOK)) == NULL) {
457 dPrintf(D_M_RTMP, D_L_WARNING,
458 ("rtmptable: Can't allocate ZT_table\n"));
459 return (ENOMEM);
460 }
461 dPrintf(D_M_RTMP, D_L_STARTUP, ("rt_table_init called\n"));
462 bzero(&RT_table[0], sizeof(RT_entry)* RT_maxentry);
463 for (i= 1 ; i < RT_maxentry ; i++) {
464 (&RT_table[i-1])->right = &RT_table[i];
465 }
466 RT_table_freelist = &RT_table[0];
467
468 at_state.flags |= AT_ST_RT_CHANGED;
469 at_state.flags |= AT_ST_ZT_CHANGED;
470 bzero(&RT_table_start, sizeof(RT_entry));
471
472 /* also clean up the ZIP table */
473
474 bzero(&ZT_table[0], sizeof(ZT_entry)* ZT_maxentry);
475 ErrorRTMPoverflow = 0;
476 ErrorZIPoverflow = 0;
477 return(0);
478}
479
480/*
481 * zt_add_zone: add a zone name in the zone table.
482 */
483
484zt_add_zone(name, length)
485char *name;
486short length;
487{
488 at_nvestr_t zname;
489 bcopy(name, &zname.str, length);
490 zname.len = length;
491 return (zt_add_zonename(&zname));
492}
493
494/*
495 * zt_add_zonename: add a zone name in the zone table.
496 */
497
498int zt_add_zonename(zname)
499at_nvestr_t *zname;
500{
501 register short res,i;
502 register unsigned int s;
503
504 if (res = zt_find_zname(zname))
505 return(res);
506
507 ATDISABLE(s, ddpinp_lock);
508 for (i = 0; i < ZT_maxentry ; i++) {
509 if (ZT_table[i].ZoneCount == 0 && ZT_table[i].Zone.len == 0) {/* free entry */
510 ZT_table[i].Zone = *zname;
511 dPrintf(D_M_RTMP, D_L_VERBOSE, ("zt_add_zonename: zone #%d %s len=%d\n",
512 i, ZT_table[i].Zone.str, ZT_table[i].Zone.len));
513 at_state.flags |= AT_ST_ZT_CHANGED;
514 ATENABLE(s, ddpinp_lock);
515 return(i+1);
516 }
517 }
518 ATENABLE(s, ddpinp_lock);
519 /* table full... */
520 return (ZT_MAXEDOUT);
521}
522
523/* Adjust zone counts for a removed network entry.
524 * If the ZoneCount of a zone reaches zero, delete the zone from the zone table
525 */
526void zt_remove_zones(zmap)
527u_char *zmap;
528{
529
530 register u_short i,j, Index;
531
532 for (i=0; i< ZT_BYTES ; i++) {
533
534 if (zmap[i]) {
535 for (j=0; j < 8 ; j++)
536 if ((zmap[i] << j) & 0x80) {
537 Index = i*8 + j; /* get the index in ZT */
538 /* 1-23-97 this routine caused a crash once, presumably
539 zmap bits beyond ZT_table size got set somehow.
540 prevent that here
541 */
542 if (Index >= ZT_maxentry) {
543 dPrintf(D_M_RTMP, D_L_ERROR,
544 ("zt_remove_zones: index (%d) GT ZT_maxentry (%d) (zmap:%d)\n",
545 Index,ZT_maxentry,i));
546 return;
547 }
548 dPrintf(D_M_RTMP, D_L_VERBOSE,
549 ("zt_remove_zones: zone #%d %s was=%d\n", Index,
550 ZT_table[Index].Zone.str, ZT_table[Index].ZoneCount));
551 if (ZT_table[Index].ZoneCount > 0)
552 ZT_table[Index].ZoneCount--;
553 if (ZT_table[Index].ZoneCount == 0)
554 ZT_table[Index].Zone.len = 0;
555 at_state.flags |= AT_ST_ZT_CHANGED;
556 }
557 }
558 }
559}
560
561
562
563/*
564 * zt_compute_hash: compute hash index from the zone name string
565 */
566
567short zt_compute_hash(zname)
568at_nvestr_t *zname;
569{
570 register u_short checksum=0, i;
571 register char c1;
572
573 /* apply the upper name + DDP checksum algorithm */
574
575 for (i= 0 ; i < zname->len; i++) {
576
577 /* upperize the character */
578
579 c1 = zname->str[i];
580 if (c1 >= 'a' && c1 <= 'z')
581 c1 += 'A' - 'a';
582 if (c1 & 0x80)
583 c1 = upshift8(c1);
584
585 /* DDP Checksum */
586
587 checksum += c1;
588 checksum = ((checksum & 0x8000) ?
589 (checksum << 1 | 1) : (checksum << 1));
590 }
591
592 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("zt_comphash: value computed for zone=%s h=%d\n",
593 zname->str, checksum));
594
595 if (checksum)
596 return (checksum);
597 else
598 return (0xffff);
599
600}
601
602/*
603 * zt_upper_zname: translate the name string into uppercase
604 */
605
606void zt_upper_zname(zname)
607at_nvestr_t *zname;
608{
609 register short i;
610 register char c1;
611
612 for (i= 0 ; i < zname->len; i++) {
613
614 c1 = zname->str[i];
615 if (c1 >= 'a' && c1 <= 'z')
616 c1 += 'A' - 'a';
617 if (c1 & 0x80)
618 c1 = upshift8(c1);
619
620 zname->str[i] = c1;
621 }
622}
623
624/*
625 * zt_get_zmcast: calcularte the zone multicast address for a
626 * given zone name.
627 * Returns the result in "buffer"
628 */
629
630zt_get_zmcast(ifID, zname, buffer)
631 at_ifaddr_t *ifID; /* we want to know the media type */
632 at_nvestr_t *zname; /* source name for multicast address */
633 char *buffer; /* resulting Zone Multicast address */
634{
635 u_short h;
636
637 h = zt_compute_hash(zname);
638
639/*
640 * Find a nice way to decide if it is TokenRing or Ethernet for
641 * the Multicast address computation....
642 */
643
644 if (ifID->aa_ifp->if_type != IFT_ISO88025) { /* token ring */
645
646 /* Ethernet case */
647
648 buffer[0] = 0x09;
649 buffer[1] = 0x00;
650 buffer[2] = 0x07;
651 /* no router, use cable multicast */
652 if (MULTIHOME_MODE && ifID->ifRouterState == NO_ROUTER ) {
653 buffer[3] = buffer[4] = buffer[5] = 0xff;
654 }
655 else {
656 buffer[3] = 0x00;
657 buffer[4] = 0x00;
658 buffer[5] = h % 0xFD;
659 }
660 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("zt_get_multi: computed for h=%d %x %x\n",
661 h, *(u_int *)&buffer[0], *(u_short *)&buffer[4]));
662
663 return(6); /* returns Multicast address length */
664
665 }
666 else {
667 /* assume it is token ring: note for the magic number computation,
668 * first see Inside Mac Page 3-10, there is 20 multicast addresses
669 * for TLAP, and they are from 0xC000 0000 0008 00 to 0xC000 0200 0000 00
670 */
671 buffer[0] = 0xC0;
672 buffer[1] = 0x00;
673 *(u_int *)&buffer[2] = 1 << ((h % 19) + 11);
674 dPrintf(D_M_RTMP, D_L_WARNING,("zt_get_multi: BROAD not found forr h=%d \n",
675 h));
676 return(6);
677 }
678
679
680
681}
682
683/*
684 * zt_ent_zindex: return the first zone index found in the zone map
685 * return the entry number+1 in the Zone Table, or zero if not found
686 */
687
688int zt_ent_zindex(zmap)
689u_char *zmap;
690{
691 u_short i,j;
692
693
694 for (i = 0 ; i < ZT_BYTES ; i++)
695
696 if (zmap[i])
697 for (j = 0 ; j < 8 ; j++)
698 if ((zmap[i] << j) & 0x80)
699 return (8*i + j +1);
700
701 return (0);
702}
703/*
704 * zt_ent_zcount: count the number of actives zone for a routing entry
705 */
706
707zt_ent_zcount(ent)
708RT_entry *ent;
709{
710 register u_char *zmap;
711 register u_short i,j;
712 register int zone_count = 0 ;
713 register unsigned int s;
714
715 ATDISABLE(s, ddpinp_lock);
716
717 if (!RT_ALL_ZONES_KNOWN(ent)) {
718 ATENABLE(s, ddpinp_lock);
719 return (0);
720 }
721 zmap = ent->ZoneBitMap;
722
723 for (i = 0 ; i < ZT_BYTES ; i++) {
724
725 if (*zmap)
726
727 for (j = 0 ; j < 8 ; j++)
728 if ((*zmap << j) & 0x80)
729 zone_count++;
730 zmap++;
731 }
732
733 ATENABLE(s, ddpinp_lock);
734 return (zone_count);
735}
736
737/*
738 * zt_find_zname: match a zone name in the zone table and return the entry if found
739 */
740zt_find_zname(zname)
741at_nvestr_t *zname;
742{
743 register short i, j, found;
744 register char c1, c2;
745 register unsigned int s;
746
747
748 if (!zname->len)
749 return(0);
750
751 ATDISABLE(s, ddpinp_lock);
752 for (i = 0 ; i < ZT_maxentry ; i++) {
753 if (!ZT_table[i].ZoneCount || zname->len != ZT_table[i].Zone.len)
754 continue;
755
756 found = 1; /* did we get the right one? */
757
758 for (j = 0 ; j < zname->len ; j++) {
759 c1 = zname->str[j];
760 c2 = ZT_table[i].Zone.str[j];
761 if (c1 >= 'a' && c1 <= 'z')
762 c1 += 'A' - 'a';
763 if (c2 >= 'a' && c2 <= 'z')
764 c2 += 'A' - 'a';
765 if (c1 & 0x80)
766 c1 = upshift8(c1);
767 if (c2 & 0x80)
768 c2 = upshift8(c2);
769 if (c1 != c2) {
770 found = 0;
771 break;
772 }
773 }
774
775 if (found) {
776 ATENABLE(s, ddpinp_lock);
777 return (i+1);
778 }
779 }
780
781 ATENABLE(s, ddpinp_lock);
782 return(0);
783}
784
785
786/*
787 * zt_set_zmap: set a bit for the corresponding zone map in an entry bitmap
788 */
789void zt_set_zmap(znum, zmap)
790 u_short znum;
791 char *zmap;
792{
793 register u_short num = znum -1;
794 register unsigned int s;
795
796 ATDISABLE(s, ddpinp_lock);
797 if (!(zmap[num >> 3] & 0x80 >> (num % 8))) {
798 zmap[num >> 3] |= 0x80 >> (num % 8);
799 ZT_table[num].ZoneCount++;
800 }
801 ATENABLE(s, ddpinp_lock);
802}
803
804
805/*
806 * zt_clr_zmap: clear a bit for the corresponding zone map in an entry bitmap
807 */
808void zt_clr_zmap(znum, zmap)
809 u_short znum;
810 char *zmap;
811{
812 register u_short num = znum -1;
813 register unsigned int s;
814
815 ATDISABLE(s, ddpinp_lock);
816 if (zmap[num >> 3] & 0x80 >> (num % 8)) {
817 zmap[num >> 3] ^= 0x80 >> (num % 8);
818 ZT_table[num].ZoneCount--;
819 }
820 ATENABLE(s, ddpinp_lock);
821}
822
823
824/*
825 * routing_needed :
826 * This function performs the actual lookup and forward of packets
827 * send to the box for routing.
828 *
829 * The destination network is looked up in our tables, and if we
830 * know the next IR to send the packet to, we forward the packet
831 * on the right port.
832 *
833 * If the destination is unknown, we simply dump the packet.
834 */
835
836void routing_needed(mp, ifID, bypass)
837 gbuf_t *mp;
838 at_ifaddr_t *ifID;
839 char bypass; /* set by special socket handlers */
840{
841
842 register at_ddp_t *ddp;
843 register int msgsize;
844 register RT_entry *Entry;
845 register gbuf_t *tmp_m;
846
847 /* first check the interface is up and forwarding */
848
849 if (!ifID) {
850 dPrintf(D_M_RTMP, D_L_WARNING,
851 ("routing_needed: non valid IFID!\n"));
852 gbuf_freel(mp);
853 return;
854 }
855 if ((ifID->ifRoutingState < PORT_ONLINE)) {
856 dPrintf(D_M_RTMP, D_L_WARNING,
857 ("routing_needed: port %d not online yet\n",
858 ifID->ifPort));
859 gbuf_freel(mp);
860 return;
861 }
862
863 ddp = (at_ddp_t *)gbuf_rptr(mp);
864 msgsize = DDPLEN_VALUE(ddp);
865 for (tmp_m = gbuf_next(mp); tmp_m; tmp_m = gbuf_next(tmp_m))
866 msgsize += DDPLEN_VALUE(((at_ddp_t *)gbuf_rptr(tmp_m)));
867
868 if (ddp->hopcount++ > 15) {
869 dPrintf(D_M_RTMP, D_L_WARNING,
870 ("routing_needed: drop packet for %d:%d, hopcount too high\n",
871 NET_VALUE(ddp->dst_net), ddp->dst_node));
872 gbuf_freel(mp);
873 snmpStats.dd_hopCount++;
874 return; /* was return(1); */
875 }
876
877 if ((Entry = rt_blookup(NET_VALUE(ddp->dst_net)))) {
878
879 dPrintf(D_M_RTMP_LOW, D_L_ROUTING,
880 ("routing_needed: FOUND for %d.%d p=%d to %d.%d \n",
881 NET_VALUE(ddp->dst_net), ddp->dst_node, ifID->ifPort,
882 Entry->NextIRNet, Entry->NextIRNode));
883
884 /* somehow, come to that point... */
885
9bccf70c
A
886 /* if multihomed - need to set source address to the interface
887 * the packet is being sent from.
888 */
889 if (MULTIHOME_MODE) {
890 NET_ASSIGN(ddp->src_net, ifID_table[Entry->NetPort]->ifThisNode.s_net);
891 ddp->src_node = ifID_table[Entry->NetPort]->ifThisNode.s_node;
892 }
893
1c79356b
A
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; /* was 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 ifID_home->ifThisNode.s_net,
931 ifID_home->ifThisNode.s_node));
932
933 ifID->ifStatistics.droppedPkts++;
934 ifID->ifStatistics.droppedBytes += msgsize;
935 snmpStats.dd_noRoutes++;
936
937 gbuf_freel(mp);
938 return; /* was return (2); */
939
940 }
941 /* return(0); */
942} /* routing_needed */
943
944ZT_entryno *zt_getNextZone(first)
945 int first;
946 /* a call made with first = TRUE returns the first valid entry in
947 the ZT_table, if first != TRUE, then then each call returns the
948 next valid entry in the table. The next call after the last
949 valid entry was read returns NULL
950 */
951{
952 int i;
953 static int idx=0;
954 static ZT_entryno zte;
955
956 if (!ZT_table)
957 return NULL;
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
976RT_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 (!RT_table)
990 return(NULL);
991
992 if (first)
993 idx=0;
994
995 for (i=idx; i<RT_maxentry; i++) {
996 if (RT_table[i].EntryState != RTE_STATE_UNUSED)
997 break;
998 }
999 if (i<RT_maxentry) {
1000 idx = i+1;
1001 return(&RT_table[i]);
1002 }
1003 else
1004 return(NULL);
1005}
1006
1007
1008getRtmpTableSize()
1009{
1010 register int i;
1011 register RT_entry *rt;
1012 static int size=0;
1013
1014 if(!(at_state.flags &AT_ST_RT_CHANGED))
1015 return(size);
1016
1017 for (i=RT_maxentry,rt = &RT_table[RT_maxentry-1]; i; i--,rt--)
1018 if (rt->EntryState != RTE_STATE_UNUSED) {
1019 size = i;
1020 return(i);
1021 }
1022 return(0);
1023}
1024
1025getZipTableSize()
1026{
1027 register int i;
1028 register ZT_entry *zt;
1029 static int size=0;
1030
1031 if (!(at_state.flags & AT_ST_ZT_CHANGED))
1032 return(size);
1033
1034 for (i=ZT_maxentry,zt = &ZT_table[ZT_maxentry-1]; i; i--,zt--)
1035 if (zt->ZoneCount) {
1036 size = i;
1037 return(i);
1038 }
1039 return(0);
1040}
1041
1042getRtmpTable(d,s,c)
1043 RT_entry *d; /* destination */
1044 int s; /* starting entry */
1045 int c; /* # entries to copy */
1046{
1047 register int i,n=0;
1048 register RT_entry *rt;
1049
1050 for(i=s,rt=&RT_table[s]; i<RT_maxentry && n<c; rt++,i++)
1051 if (rt->EntryState != RTE_STATE_UNUSED) {
1052 *d++ = *rt;
1053 n++;
1054 }
1055}
1056
1057getZipTable(d,s,c)
1058 ZT_entry *d; /* destination */
1059 int s; /* starting entry */
1060 int c; /* # entries to copy */
1061{
1062
1063 bcopy(&ZT_table[s], d, c*sizeof(ZT_entry));
1064}
1065
1066at_nvestr_t *getRTRLocalZone(ifz)
1067 zone_usage_t *ifz;
1068{
1069 char *zmap;
1070 RT_entry *route;
1071 int i, j, index;
1072 int zcnt=0; /* zone we're pointing to in the list */
1073 char zonesChecked[ZT_BYTES];
1074 at_ifaddr_t *ifID;
1075
1076 if (ifz->zone_index < 0) {
1077 return((at_nvestr_t*)NULL);
1078 }
1079 bzero(zonesChecked,sizeof(zonesChecked));
1080 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
1081 if (!(route = rt_blookup(ifID->ifThisNode.s_net))) {
1082 return((at_nvestr_t*)NULL);
1083 }
1084 zmap=route->ZoneBitMap;
1085 dPrintf(D_M_RTMP_LOW, D_L_USR1,
1086 ("getRTRLocal: i/f %s, net:%d\n",ifID->ifName,
1087 ifID->ifThisNode.s_net));
1088 for (i = 0 ; i < ZT_BYTES; i++) {
1089 if (zmap[i]) {
1090 for (j = 0; j < 8 ; j++)
1091 if ( (zmap[i] & (0x80 >> j)) &&
1092 !(zonesChecked[i] & (0x80 >> j))
1093 ) {
1094 zonesChecked[i] |= (0x80 >> j);
1095 if (ifz->zone_index == zcnt) {
1096 index = i * 8 + j;
1097 getIfUsage(index, &ifz->zone_iflist);
1098 ifz->zone_name = ZT_table[index].Zone;
1099 dPrintf(D_M_RTMP_LOW, D_L_USR1,
1100 ("getRTRLocal:zmap:%8x zcnt:%d\n",
1101 *(int*)zmap, zcnt));
1102 ifz->zone_index = index+1;
1103 return(&ZT_table[index].Zone);
1104 }
1105 zcnt++;
1106 }
1107 }
1108 }
1109 }
1110 dPrintf(D_M_RTMP_LOW, D_L_USR1,
1111 ("getRTRLocal: returning NULL last ent:%d net:%d zmap:%08x\n",
1112 (ifID ? ifID->ifPort : 0),
1113 (ifID ? ifID->ifThisNode.s_net : 0),*(int*)zmap));
1114 ifz->zone_name.len = 0;
1115 return((at_nvestr_t*)NULL);
1116} /* getRTRLocalZone */
1117
1118void getIfUsage(zone, ifs_in_zone)
1119 int zone;
1120 at_ifnames_t *ifs_in_zone;
1121
9bccf70c
A
1122/* sets the interface name in each element of the array for each I/F in the
1123 requested zone. The array has a 1:1 correspondence with the
1c79356b
A
1124 ifID_table. Zone is assumed to be valid and local, so if we're in
1125 single port mode, we'll set the home port and thats it.
1126*/
1127{
1128 u_int zmi; /* zone map index for zone */
1129 u_char zmb; /* zone map bit mask for zone */
1130 RT_entry *route;
1131 int cnt=0;
1132 at_ifaddr_t *ifID;
1133
1134 if (!MULTIPORT_MODE) {
1135 strncpy(ifs_in_zone->at_if[cnt], ifID_home->ifName,
1136 IFNAMESIZ);
1137 return;
1138 }
1139 bzero(ifs_in_zone, sizeof(at_ifnames_t));
1140 zmi = zone>>3;
1141 zmb = 0x80>>(zone % 8);
1142 dPrintf(D_M_NBP_LOW, D_L_USR3, ("get_ifs znum:%d zmi%d zmb:%x\n",
1143 zone, zmi, zmb));
1144 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
1145 if (!(route = rt_blookup(ifID->ifThisNode.s_net)))
1146 return;
1147 if (route->ZoneBitMap[zmi] & zmb) {
1148 dPrintf(D_M_NBP_LOW, D_L_USR3, ("zone in port %d \n",
1149 route->NetPort));
1150 strncpy(ifs_in_zone->at_if[cnt],
1151 ifID_table[route->NetPort]->ifName, IFNAMESIZ);
1152 cnt++;
1153 }
1154 }
1155 return;
1156} /* getIfUsage */