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