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