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