]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/ddp_rtmptable.c
ebc2fe951bf12d3c489aa8fc5940ac30d1bd8ada
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 /*----------------------------------------------------------------------------
32 * RTMP & ZIP routing tables access routines
34 * This code implement b-tree search and manipulation of
35 * of the RTMP routing table and ZIP zone table.
37 * The RTMP routing table is a data block divided in several routing
38 * entries sorted during insertion in a b-tree form. We use a table and
39 * not dynamically allocated entries because it allow us to scan the whole
40 * table when RTMP packets are generated. The routing table entries are sorted
41 * by there NetStop value (because non extended nets have a NetStart value of
42 * zero. From any point in the tree, the left side contains Network ranges
43 * smaller or equal to the current Node, and the right tree points to higher
44 * values network ranges.
47 * 0.01 3/16/94 LD Creation
48 * Modified for MP, 1996 by Tuyen Nguyen
49 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
51 *----------------------------------------------------------------------------
53 * Copyright (c) 1994, 1996, 1997, 1998 Apple Computer, Inc.
56 #include <sys/errno.h>
57 #include <sys/types.h>
58 #include <sys/param.h>
59 #include <machine/spl.h>
60 #include <sys/systm.h>
61 #include <sys/kernel.h>
63 #include <sys/filedesc.h>
64 #include <sys/fcntl.h>
66 #include <sys/ioctl.h>
67 #include <sys/malloc.h>
68 #include <sys/socket.h>
69 #include <sys/socketvar.h>
72 #include <net/if_types.h>
74 #include <netat/sysglue.h>
75 #include <netat/appletalk.h>
76 #include <netat/at_var.h>
77 #include <netat/ddp.h>
78 #include <netat/rtmp.h>
79 #include <netat/at_pcb.h>
80 #include <netat/zip.h>
81 #include <netat/routing_tables.h>
82 #include <netat/at_snmp.h>
83 #include <netat/debug.h>
85 RT_entry
*RT_table_freelist
; /* start of free entry list */
86 RT_entry RT_table_start
; /* start of the actual entry table */
87 RT_entry
*RT_table
; /* the routing table */
88 ZT_entry
*ZT_table
; /* the Zone Information Protocol table */
89 short RT_maxentry
; /* Number of entry in RTMP table */
90 short ZT_maxentry
; /* Number of entry in ZIP table */
92 char errstr
[512]; /* used to display meaningfull router errors*/
94 extern at_ifaddr_t
*ifID_table
[];
95 extern at_ifaddr_t
*ifID_home
;
96 extern snmpStats_t snmpStats
;
97 extern atlock_t ddpinp_lock
;
99 short ErrorRTMPoverflow
= 0; /* flag if RTMP table is too small for this net */
100 short ErrorZIPoverflow
= 0; /* flag if ZIP table is too small for this net */
103 void getIfUsage( int, at_ifnames_t
*);
106 * This a temporary function : just to display the router error
109 void RouterError(port
, err_number
)
110 short port
, err_number
;
113 switch (err_number
) {
115 case ERTR_SEED_CONFLICT
:
116 dPrintf(D_M_RTMP
, D_L_ERROR
,
117 ("**** RTR Error on port# %d SEED_CONFLICT\n", port
));
120 case ERTR_CABLE_CONFLICT
:
121 dPrintf(D_M_RTMP
, D_L_ERROR
,
122 ("**** RTR Error on port# %d CABLE_CONFLICT\n", port
));
125 case ERTR_RTMP_BAD_VERSION
:
126 dPrintf(D_M_RTMP
, D_L_ERROR
,
127 ("**** RTR Error on port# %d RTMP_BAD_VERSION\n", port
));
130 case ERTR_CABLE_STARTUP
:
131 dPrintf(D_M_RTMP
, D_L_ERROR
,
132 ("**** RTR Error on port# %d RTMP_CABLE_STARTUP\n",
137 dPrintf(D_M_RTMP
, D_L_ERROR
,
138 ("**** RTR Error on port# %d WHAT IN THE WORLD IS THIS ONE? code=%d\n",
142 dPrintf(D_M_RTMP
, D_L_ERROR
, ("Explanation: %s\n", errstr
));
147 * this function just look for a NetNumber in the routing table,
148 * no check is done for the validity of the entry
151 RT_entry
*rt_blookup (NetNumber
)
155 RT_entry
*ptree
= &RT_table_start
;
157 register unsigned int s
;
159 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Lookup for Net=%d\n",
160 "rt_blookup", NetNumber));
162 ATDISABLE(s
, ddpinp_lock
);
165 if (NetNumber
> ptree
->NetStop
) {
167 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Go Right from #%d\n",
168 "rt_blookup", ptree->NextIRNet));
170 ptree
= ptree
->right
;
175 LowEnd
= ptree
->NetStart
;
177 LowEnd
= ptree
->NetStop
;
179 if (NetNumber
< LowEnd
) {
181 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : Go Left from #%d\n",
182 "rt_blookup", ptree->NextIRNet));
187 ATENABLE(s
, ddpinp_lock
);
189 /* we're in the range (either extended or not)
190 * return the entry found.
193 /* dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : found %04d-%04d Port=%d State=0x%x\n",
194 "rt_blookup", ptree->NetStart, ptree->NetStop, ptree->NetPort,
201 ATENABLE(s
, ddpinp_lock
);
203 dPrintf(D_M_RTMP_LOW
, D_L_ROUTING
, ("%s : %04d : NOT FOUND\n",
204 "rt_blookup", NetNumber
));
205 return ((RT_entry
*)NULL
);
209 /* Routing table btree insert routine
210 * Uses a RT_entry parameter as the input, the insert is sorted in
211 * the tree on the NetStop field. Provision is made for non extented
212 * net (ie NetStart = 0).
213 * The function returns the element where the new entry was inserted, or
214 * NULL if the insert didn't work. (In this cas there is a problem with
215 * the tree coherency...
220 RT_entry
*rt_binsert (NewEntry
)
223 RT_entry
*ptree
= &RT_table_start
;
225 register at_net_al NetStart
= NewEntry
->NetStart
;
226 register at_net_al NetStop
= NewEntry
->NetStop
;
228 dPrintf(D_M_RTMP_LOW
, D_L_ROUTING
, ("rt_binsert: for Net %d-%d state=x%x NextIR %d:%d\n",
229 NetStart
, NetStop
, NewEntry
->EntryState
,NewEntry
->NextIRNet
, NewEntry
->NextIRNode
));
231 if (ptree
== (RT_entry
*)NULL
) {
233 at_state
.flags
|= AT_ST_RT_CHANGED
;
240 if (NetStop
> ptree
->NetStop
) { /* walk the right sub-tree */
242 ptree
= ptree
->right
;
244 ptree
->right
= NewEntry
;
245 at_state
.flags
|= AT_ST_RT_CHANGED
;
249 else { /* walk the left sub-tree */
253 ptree
->left
= NewEntry
;
254 at_state
.flags
|= AT_ST_RT_CHANGED
;
261 dPrintf(D_M_RTMP
, D_L_WARNING
, ("%s : ERROR NOT INSERTED Net %d-%d\n",
262 "rt_binsert", NetStart
, NetStop
));
263 return ((RT_entry
*)NULL
);
266 RT_entry
*rt_insert(NStop
, NStart
, NxNet
, NxNode
, NtDist
, NtPort
, EntS
)
267 at_net_al NStop
, NStart
, NxNet
;
269 u_char NtDist
, NtPort
, EntS
;
272 if ((New
= RT_table_freelist
)) {
273 RT_table_freelist
= RT_table_freelist
->right
;
275 return ((RT_entry
*)NULL
);
277 New
->NetStop
= NStop
;
278 New
->NetStart
= NStart
;
279 New
->NextIRNet
= NxNet
;
280 New
->NextIRNode
= NxNode
;
281 New
->NetDist
= NtDist
;
282 New
->NetPort
= NtPort
;
283 New
->EntryState
= EntS
;
284 bzero(New
->ZoneBitMap
, sizeof(New
->ZoneBitMap
));
285 at_state
.flags
|= AT_ST_RT_CHANGED
;
286 return(rt_binsert(New
));
290 dPrintf(D_M_RTMP_LOW, D_L_ROUTING, ("%s : %04d : NOT FOUND\n",
291 "rt_blookup", NetNumber));
292 * Routing table btree deletion routine
296 RT_entry
*rt_bdelete (NetStop
, NetStart
)
297 at_net_al NetStop
, NetStart
;
300 RT_entry
*rt_found
, *pprevious
, *pnext
, *pnextl
, *psub
;
303 rt_found
= &RT_table_start
;
305 dPrintf(D_M_RTMP_LOW
, D_L_ROUTING
, ("%s : Delete %d-%d\n",
306 "rt_bdelete", NetStart
, NetStop
));
310 if (NetStop
> rt_found
->NetStop
) {
311 pprevious
= rt_found
;
312 rt_found
= rt_found
->right
;
317 /* non extended nets cases */
319 if (rt_found
->NetStart
)
320 LowEnd
= rt_found
->NetStart
;
322 LowEnd
= rt_found
->NetStop
;
324 if (NetStop
< LowEnd
) {
325 pprevious
= rt_found
;
326 rt_found
= rt_found
->left
;
330 /* we're in the range (either extended or not)
331 * return the entry found.
338 dPrintf(D_M_RTMP
, D_L_ROUTING
, ("%s : Delete %d-%d found to delete %d-%d\n",
339 "rt_bdelete", NetStart
, NetStop
, rt_found
->NetStart
,rt_found
->NetStop
));
345 /* we found the entry, now reorg the sub-trees
346 * spanning from our node.
349 if ((pnext
= rt_found
->right
)) {
351 /* Tree pruning: take the left branch of the current
352 * node and place it at the lowest left branch
353 * of the current right branch
358 /* walk the Right/Left sub tree from current node */
360 while ((pnextl
= psub
->left
))
363 /* plug the old left tree to the new ->Right leftmost node */
365 psub
->left
= rt_found
->left
;
368 } else { /* only left sub-tree, simple case */
370 pnext
= rt_found
->left
;
373 /* Now, plug the current node sub tree to the good pointer of
378 if (pprevious
->left
== rt_found
)
379 pprevious
->left
= pnext
;
381 pprevious
->right
= pnext
;
383 /* clean-up entry and add to the free-list */
385 at_state
.flags
|= AT_ST_RT_CHANGED
;
389 else { /* Trying to delete something that doesn't exist? */
391 dPrintf(D_M_RTMP
, D_L_WARNING
, ("%s : %d NOT Removed\n",
392 "rt_bdelete", NetStop
));
394 return ((RT_entry
*)NULL
);
401 RT_entry
*rt_sortedshow(parent
)
408 if (parent
== NULL
) {
409 me
= &RT_table_start
;
415 /* parent = parent->parent; */
421 * debug only: display the contents of the routing table
429 ptree
= &RT_table
[0];
431 while (ptree
&& i
< 600 ) {
432 if (ptree
->NetStop
) {
433 dPrintf(D_M_RTMP_LOW
, D_L_VERBOSE
,
434 ("%4d-%4d IR=%d:%d Dist=%d\n",
435 ptree
->NetStop
, ptree
->NetStart
, ptree
->NextIRNet
,
436 ptree
->NextIRNode
, (short)ptree
->NetDist
));
438 dPrintf(D_M_RTMP_LOW
, D_L_VERBOSE
,
439 ("%04d : * FREE ENTRY\n", i
));
447 * prepare the indexing of the free entries in the RTMP table
454 if ((RT_table
= (RT_entry
*)_MALLOC(sizeof(RT_entry
)*RT_maxentry
,
455 M_RTABLE
, M_WAITOK
)) == NULL
) {
456 dPrintf(D_M_RTMP
, D_L_WARNING
,
457 ("rtmptable: Can't allocate RT_table\n"));
460 if ((ZT_table
= (ZT_entry
*)_MALLOC(sizeof(ZT_entry
)*ZT_maxentry
,
461 M_RTABLE
, M_WAITOK
)) == NULL
) {
462 dPrintf(D_M_RTMP
, D_L_WARNING
,
463 ("rtmptable: Can't allocate ZT_table\n"));
466 dPrintf(D_M_RTMP
, D_L_STARTUP
, ("rt_table_init called\n"));
467 bzero(&RT_table
[0], sizeof(RT_entry
)* RT_maxentry
);
468 for (i
= 1 ; i
< RT_maxentry
; i
++) {
469 (&RT_table
[i
-1])->right
= &RT_table
[i
];
471 RT_table_freelist
= &RT_table
[0];
473 at_state
.flags
|= AT_ST_RT_CHANGED
;
474 at_state
.flags
|= AT_ST_ZT_CHANGED
;
475 bzero(&RT_table_start
, sizeof(RT_entry
));
477 /* also clean up the ZIP table */
479 bzero(&ZT_table
[0], sizeof(ZT_entry
)* ZT_maxentry
);
480 ErrorRTMPoverflow
= 0;
481 ErrorZIPoverflow
= 0;
486 * zt_add_zone: add a zone name in the zone table.
489 zt_add_zone(name
, length
)
494 bcopy(name
, &zname
.str
, length
);
496 return (zt_add_zonename(&zname
));
500 * zt_add_zonename: add a zone name in the zone table.
503 int zt_add_zonename(zname
)
506 register short res
,i
;
507 register unsigned int s
;
509 if (res
= zt_find_zname(zname
))
512 ATDISABLE(s
, ddpinp_lock
);
513 for (i
= 0; i
< ZT_maxentry
; i
++) {
514 if (ZT_table
[i
].ZoneCount
== 0 && ZT_table
[i
].Zone
.len
== 0) {/* free entry */
515 ZT_table
[i
].Zone
= *zname
;
516 dPrintf(D_M_RTMP
, D_L_VERBOSE
, ("zt_add_zonename: zone #%d %s len=%d\n",
517 i
, ZT_table
[i
].Zone
.str
, ZT_table
[i
].Zone
.len
));
518 at_state
.flags
|= AT_ST_ZT_CHANGED
;
519 ATENABLE(s
, ddpinp_lock
);
523 ATENABLE(s
, ddpinp_lock
);
525 return (ZT_MAXEDOUT
);
528 /* Adjust zone counts for a removed network entry.
529 * If the ZoneCount of a zone reaches zero, delete the zone from the zone table
531 void zt_remove_zones(zmap
)
535 register u_short i
,j
, Index
;
537 for (i
=0; i
< ZT_BYTES
; i
++) {
540 for (j
=0; j
< 8 ; j
++)
541 if ((zmap
[i
] << j
) & 0x80) {
542 Index
= i
*8 + j
; /* get the index in ZT */
543 /* 1-23-97 this routine caused a crash once, presumably
544 zmap bits beyond ZT_table size got set somehow.
547 if (Index
>= ZT_maxentry
) {
548 dPrintf(D_M_RTMP
, D_L_ERROR
,
549 ("zt_remove_zones: index (%d) GT ZT_maxentry (%d) (zmap:%d)\n",
550 Index
,ZT_maxentry
,i
));
553 dPrintf(D_M_RTMP
, D_L_VERBOSE
,
554 ("zt_remove_zones: zone #%d %s was=%d\n", Index
,
555 ZT_table
[Index
].Zone
.str
, ZT_table
[Index
].ZoneCount
));
556 if (ZT_table
[Index
].ZoneCount
> 0)
557 ZT_table
[Index
].ZoneCount
--;
558 if (ZT_table
[Index
].ZoneCount
== 0)
559 ZT_table
[Index
].Zone
.len
= 0;
560 at_state
.flags
|= AT_ST_ZT_CHANGED
;
569 * zt_compute_hash: compute hash index from the zone name string
572 short zt_compute_hash(zname
)
575 register u_short checksum
=0, i
;
578 /* apply the upper name + DDP checksum algorithm */
580 for (i
= 0 ; i
< zname
->len
; i
++) {
582 /* upperize the character */
585 if (c1
>= 'a' && c1
<= 'z')
593 checksum
= ((checksum
& 0x8000) ?
594 (checksum
<< 1 | 1) : (checksum
<< 1));
597 dPrintf(D_M_RTMP_LOW
, D_L_ROUTING
, ("zt_comphash: value computed for zone=%s h=%d\n",
598 zname
->str
, checksum
));
608 * zt_upper_zname: translate the name string into uppercase
611 void zt_upper_zname(zname
)
617 for (i
= 0 ; i
< zname
->len
; i
++) {
620 if (c1
>= 'a' && c1
<= 'z')
630 * zt_get_zmcast: calcularte the zone multicast address for a
632 * Returns the result in "buffer"
635 zt_get_zmcast(ifID
, zname
, buffer
)
636 at_ifaddr_t
*ifID
; /* we want to know the media type */
637 at_nvestr_t
*zname
; /* source name for multicast address */
638 char *buffer
; /* resulting Zone Multicast address */
642 h
= zt_compute_hash(zname
);
645 * Find a nice way to decide if it is TokenRing or Ethernet for
646 * the Multicast address computation....
649 if (ifID
->aa_ifp
->if_type
!= IFT_ISO88025
) { /* token ring */
656 /* no router, use cable multicast */
657 if (MULTIHOME_MODE
&& ifID
->ifRouterState
== NO_ROUTER
) {
658 buffer
[3] = buffer
[4] = buffer
[5] = 0xff;
663 buffer
[5] = h
% 0xFD;
665 dPrintf(D_M_RTMP_LOW
, D_L_ROUTING
, ("zt_get_multi: computed for h=%d %x %x\n",
666 h
, *(u_int
*)&buffer
[0], *(u_short
*)&buffer
[4]));
668 return(6); /* returns Multicast address length */
672 /* assume it is token ring: note for the magic number computation,
673 * first see Inside Mac Page 3-10, there is 20 multicast addresses
674 * for TLAP, and they are from 0xC000 0000 0008 00 to 0xC000 0200 0000 00
678 *(u_int
*)&buffer
[2] = 1 << ((h
% 19) + 11);
679 dPrintf(D_M_RTMP
, D_L_WARNING
,("zt_get_multi: BROAD not found forr h=%d \n",
689 * zt_ent_zindex: return the first zone index found in the zone map
690 * return the entry number+1 in the Zone Table, or zero if not found
693 int zt_ent_zindex(zmap
)
699 for (i
= 0 ; i
< ZT_BYTES
; i
++)
702 for (j
= 0 ; j
< 8 ; j
++)
703 if ((zmap
[i
] << j
) & 0x80)
709 * zt_ent_zcount: count the number of actives zone for a routing entry
715 register u_char
*zmap
;
716 register u_short i
,j
;
717 register int zone_count
= 0 ;
718 register unsigned int s
;
720 ATDISABLE(s
, ddpinp_lock
);
722 if (!RT_ALL_ZONES_KNOWN(ent
)) {
723 ATENABLE(s
, ddpinp_lock
);
726 zmap
= ent
->ZoneBitMap
;
728 for (i
= 0 ; i
< ZT_BYTES
; i
++) {
732 for (j
= 0 ; j
< 8 ; j
++)
733 if ((*zmap
<< j
) & 0x80)
738 ATENABLE(s
, ddpinp_lock
);
743 * zt_find_zname: match a zone name in the zone table and return the entry if found
748 register short i
, j
, found
;
749 register char c1
, c2
;
750 register unsigned int s
;
756 ATDISABLE(s
, ddpinp_lock
);
757 for (i
= 0 ; i
< ZT_maxentry
; i
++) {
758 if (!ZT_table
[i
].ZoneCount
|| zname
->len
!= ZT_table
[i
].Zone
.len
)
761 found
= 1; /* did we get the right one? */
763 for (j
= 0 ; j
< zname
->len
; j
++) {
765 c2
= ZT_table
[i
].Zone
.str
[j
];
766 if (c1
>= 'a' && c1
<= 'z')
768 if (c2
>= 'a' && c2
<= 'z')
781 ATENABLE(s
, ddpinp_lock
);
786 ATENABLE(s
, ddpinp_lock
);
792 * zt_set_zmap: set a bit for the corresponding zone map in an entry bitmap
794 void zt_set_zmap(znum
, zmap
)
798 register u_short num
= znum
-1;
799 register unsigned int s
;
801 ATDISABLE(s
, ddpinp_lock
);
802 if (!(zmap
[num
>> 3] & 0x80 >> (num
% 8))) {
803 zmap
[num
>> 3] |= 0x80 >> (num
% 8);
804 ZT_table
[num
].ZoneCount
++;
806 ATENABLE(s
, ddpinp_lock
);
811 * zt_clr_zmap: clear a bit for the corresponding zone map in an entry bitmap
813 void zt_clr_zmap(znum
, zmap
)
817 register u_short num
= znum
-1;
818 register unsigned int s
;
820 ATDISABLE(s
, ddpinp_lock
);
821 if (zmap
[num
>> 3] & 0x80 >> (num
% 8)) {
822 zmap
[num
>> 3] ^= 0x80 >> (num
% 8);
823 ZT_table
[num
].ZoneCount
--;
825 ATENABLE(s
, ddpinp_lock
);
831 * This function performs the actual lookup and forward of packets
832 * send to the box for routing.
834 * The destination network is looked up in our tables, and if we
835 * know the next IR to send the packet to, we forward the packet
838 * If the destination is unknown, we simply dump the packet.
841 void routing_needed(mp
, ifID
, bypass
)
844 char bypass
; /* set by special socket handlers */
847 register at_ddp_t
*ddp
;
848 register int msgsize
;
849 register RT_entry
*Entry
;
850 register gbuf_t
*tmp_m
;
852 /* first check the interface is up and forwarding */
855 dPrintf(D_M_RTMP
, D_L_WARNING
,
856 ("routing_needed: non valid IFID!\n"));
860 if ((ifID
->ifRoutingState
< PORT_ONLINE
)) {
861 dPrintf(D_M_RTMP
, D_L_WARNING
,
862 ("routing_needed: port %d not online yet\n",
868 ddp
= (at_ddp_t
*)gbuf_rptr(mp
);
869 msgsize
= DDPLEN_VALUE(ddp
);
870 for (tmp_m
= gbuf_next(mp
); tmp_m
; tmp_m
= gbuf_next(tmp_m
))
871 msgsize
+= DDPLEN_VALUE(((at_ddp_t
*)gbuf_rptr(tmp_m
)));
873 if (ddp
->hopcount
++ > 15) {
874 dPrintf(D_M_RTMP
, D_L_WARNING
,
875 ("routing_needed: drop packet for %d:%d, hopcount too high\n",
876 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
));
878 snmpStats
.dd_hopCount
++;
879 return; /* was return(1); */
882 if ((Entry
= rt_blookup(NET_VALUE(ddp
->dst_net
)))) {
884 dPrintf(D_M_RTMP_LOW
, D_L_ROUTING
,
885 ("routing_needed: FOUND for %d.%d p=%d to %d.%d \n",
886 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
, ifID
->ifPort
,
887 Entry
->NextIRNet
, Entry
->NextIRNode
));
889 /* somehow, come to that point... */
891 /* if multihomed - need to set source address to the interface
892 * the packet is being sent from.
894 if (MULTIHOME_MODE
) {
895 NET_ASSIGN(ddp
->src_net
, ifID_table
[Entry
->NetPort
]->ifThisNode
.s_net
);
896 ddp
->src_node
= ifID_table
[Entry
->NetPort
]->ifThisNode
.s_node
;
899 ifID
->ifStatistics
.fwdPkts
++;
900 ifID
->ifStatistics
.fwdBytes
+= msgsize
;
902 if (Entry
->NetDist
) /* net not directly connected */
903 ddp_router_output(mp
, ifID_table
[Entry
->NetPort
], AT_ADDR
,
904 Entry
->NextIRNet
, Entry
->NextIRNode
, 0);
905 else {/* we are directly on this net */
907 /* we want to avoid duplicating broadcast packet on the same net,
908 * but special sockets handlers are ok to do that (mainly for
909 * for loopback purpose). So, if the "bypass" flag is set, we don't
910 * check for that test... [Problem was "movietalk"].
913 if (bypass
|| ifID_table
[Entry
->NetPort
] != ifID
)
914 ddp_router_output(mp
, ifID_table
[Entry
->NetPort
], AT_ADDR
,
915 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
, 0);
917 dPrintf(D_M_RTMP
, D_L_ROUTING
,
918 ("routing_needed: bad loopback for add %d.%d from port %d (%d.%d)\n",
919 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
, ifID
->ifPort
,
920 NET_VALUE(ddp
->src_net
), ddp
->src_node
));
921 ifID
->ifStatistics
.droppedPkts
++;
922 ifID
->ifStatistics
.droppedBytes
+= msgsize
;
925 return; /* was return (2); */
932 dPrintf(D_M_RTMP
, D_L_ROUTING
,
933 ("routing_needed: NOT FOUND for add %d.%d from port %d our %d.%d\n",
934 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
, ifID
->ifPort
,
935 ifID_home
->ifThisNode
.s_net
,
936 ifID_home
->ifThisNode
.s_node
));
938 ifID
->ifStatistics
.droppedPkts
++;
939 ifID
->ifStatistics
.droppedBytes
+= msgsize
;
940 snmpStats
.dd_noRoutes
++;
943 return; /* was return (2); */
947 } /* routing_needed */
949 ZT_entryno
*zt_getNextZone(first
)
951 /* a call made with first = TRUE returns the first valid entry in
952 the ZT_table, if first != TRUE, then then each call returns the
953 next valid entry in the table. The next call after the last
954 valid entry was read returns NULL
959 static ZT_entryno zte
;
967 for (i
=idx
; i
<ZT_maxentry
; i
++) {
968 if (ZT_table
[i
].ZoneCount
)
973 zte
.zt
= ZT_table
[i
];
981 RT_entry
*rt_getNextRoute(first
)
984 /* a call made with first = TRUE returns the first valid entry in
985 the RT_table, if first != TRUE, then then each call returns the
986 next valid entry in the table. The next call after the last
987 valid entry was read returns NULL
1000 for (i
=idx
; i
<RT_maxentry
; i
++) {
1001 if (RT_table
[i
].EntryState
!= RTE_STATE_UNUSED
)
1004 if (i
<RT_maxentry
) {
1006 return(&RT_table
[i
]);
1016 register RT_entry
*rt
;
1019 if(!(at_state
.flags
&AT_ST_RT_CHANGED
))
1022 for (i
=RT_maxentry
,rt
= &RT_table
[RT_maxentry
-1]; i
; i
--,rt
--)
1023 if (rt
->EntryState
!= RTE_STATE_UNUSED
) {
1033 register ZT_entry
*zt
;
1036 if (!(at_state
.flags
& AT_ST_ZT_CHANGED
))
1039 for (i
=ZT_maxentry
,zt
= &ZT_table
[ZT_maxentry
-1]; i
; i
--,zt
--)
1040 if (zt
->ZoneCount
) {
1048 RT_entry
*d
; /* destination */
1049 int s
; /* starting entry */
1050 int c
; /* # entries to copy */
1053 register RT_entry
*rt
;
1055 for(i
=s
,rt
=&RT_table
[s
]; i
<RT_maxentry
&& n
<c
; rt
++,i
++)
1056 if (rt
->EntryState
!= RTE_STATE_UNUSED
) {
1063 ZT_entry
*d
; /* destination */
1064 int s
; /* starting entry */
1065 int c
; /* # entries to copy */
1068 bcopy(&ZT_table
[s
], d
, c
*sizeof(ZT_entry
));
1071 at_nvestr_t
*getRTRLocalZone(ifz
)
1077 int zcnt
=0; /* zone we're pointing to in the list */
1078 char zonesChecked
[ZT_BYTES
];
1081 if (ifz
->zone_index
< 0) {
1082 return((at_nvestr_t
*)NULL
);
1084 bzero(zonesChecked
,sizeof(zonesChecked
));
1085 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1086 if (!(route
= rt_blookup(ifID
->ifThisNode
.s_net
))) {
1087 return((at_nvestr_t
*)NULL
);
1089 zmap
=route
->ZoneBitMap
;
1090 dPrintf(D_M_RTMP_LOW
, D_L_USR1
,
1091 ("getRTRLocal: i/f %s, net:%d\n",ifID
->ifName
,
1092 ifID
->ifThisNode
.s_net
));
1093 for (i
= 0 ; i
< ZT_BYTES
; i
++) {
1095 for (j
= 0; j
< 8 ; j
++)
1096 if ( (zmap
[i
] & (0x80 >> j
)) &&
1097 !(zonesChecked
[i
] & (0x80 >> j
))
1099 zonesChecked
[i
] |= (0x80 >> j
);
1100 if (ifz
->zone_index
== zcnt
) {
1102 getIfUsage(index
, &ifz
->zone_iflist
);
1103 ifz
->zone_name
= ZT_table
[index
].Zone
;
1104 dPrintf(D_M_RTMP_LOW
, D_L_USR1
,
1105 ("getRTRLocal:zmap:%8x zcnt:%d\n",
1106 *(int*)zmap
, zcnt
));
1107 ifz
->zone_index
= index
+1;
1108 return(&ZT_table
[index
].Zone
);
1115 dPrintf(D_M_RTMP_LOW
, D_L_USR1
,
1116 ("getRTRLocal: returning NULL last ent:%d net:%d zmap:%08x\n",
1117 (ifID
? ifID
->ifPort
: 0),
1118 (ifID
? ifID
->ifThisNode
.s_net
: 0),*(int*)zmap
));
1119 ifz
->zone_name
.len
= 0;
1120 return((at_nvestr_t
*)NULL
);
1121 } /* getRTRLocalZone */
1123 void getIfUsage(zone
, ifs_in_zone
)
1125 at_ifnames_t
*ifs_in_zone
;
1127 /* sets the interface name in each element of the array for each I/F in the
1128 requested zone. The array has a 1:1 correspondence with the
1129 ifID_table. Zone is assumed to be valid and local, so if we're in
1130 single port mode, we'll set the home port and thats it.
1133 u_int zmi
; /* zone map index for zone */
1134 u_char zmb
; /* zone map bit mask for zone */
1139 if (!MULTIPORT_MODE
) {
1140 strncpy(ifs_in_zone
->at_if
[cnt
], ifID_home
->ifName
,
1144 bzero(ifs_in_zone
, sizeof(at_ifnames_t
));
1146 zmb
= 0x80>>(zone
% 8);
1147 dPrintf(D_M_NBP_LOW
, D_L_USR3
, ("get_ifs znum:%d zmi%d zmb:%x\n",
1149 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1150 if (!(route
= rt_blookup(ifID
->ifThisNode
.s_net
)))
1152 if (route
->ZoneBitMap
[zmi
] & zmb
) {
1153 dPrintf(D_M_NBP_LOW
, D_L_USR3
, ("zone in port %d \n",
1155 strncpy(ifs_in_zone
->at_if
[cnt
],
1156 ifID_table
[route
->NetPort
]->ifName
, IFNAMESIZ
);