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