2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1993 NeXT Computer, Inc. All rights reserved.
24 * tokensr.h - Token-ring IEEE 802.5 source routing utility functions.
26 * We currently make these functions static inlines. These should
27 * be considered for movement to a library and made public (after
32 * 22-Jul-94 John Immordino (jimmord) at NeXT
33 * Converted static array of source routes to a hash table.
34 * Loosely coupled hash table entries to arp table entries, ie.
35 * when hash table is full, delete the first entry for which there
36 * is no arp entry before inserting the next source route.
38 * 26-Apr-94 John Immordino (jimmord) at NeXT
39 * Cleaned up. Fixed byte-swap problems, converted all addresses to
40 * character arrays, etc.
42 * 07-Apr-93 Joel Greenblatt at NeXT
52 #include <sys/socket.h>
53 #include <net/tokendefs.h>
55 #include <net/if_arp.h>
56 #include <netinet/in.h>
57 #include <netinet/if_ether.h>
58 #include <objc/hashtable.h> /* Not an Obj-C header */
61 * Virtual driver parameters
62 * Used by if_vtrXX modules
73 * Source routing table entry
74 * Note: ipAddr must be the first element in order for our hash table
75 * code to work properly.
78 unsigned long ipAddr
; /* IP address of this entry - */
79 /* needed for our temporary */
80 /* arp table lookup scheme */
81 sroute_t ri
; /* routing information field */
86 * Encoded source-routing broadcast type (used as parameter to
87 * source routing routines).
90 SRB_OFF
, /* no source-route broadcast */
91 SRB_AR
, /* all-routes broadcast */
92 SRB_SR
, /* single-route broadcast */
93 SRB_INVALID
/* invalid entry */
97 * ARP code taken from bsd/netinet/if_ether.c. Need this in order
98 * to perform lookups of IP addresses to determine which source route
99 * entry to remove from the table. The first source route entry without
100 * a corresponding ARP entry will be removed.
103 #define ARPTAB_BSIZ 16 /* bucket size */
104 #define ARPTAB_NB 37 /* number of buckets */
106 #define ARPTAB_BSIZ 9 /* bucket size */
107 #define ARPTAB_NB 19 /* number of buckets */
110 extern struct arptab arptab
[];
112 #define ARPTAB_HASH(a) \
113 ((u_long)(a) % ARPTAB_NB)
116 * Change to permit multiple heterogenous interfaces to co-exist.
118 #define ARPTAB_LOOK(at,addr,ifp) { \
120 at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \
121 for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
122 if (at->at_iaddr.s_addr == addr && \
123 (!(ifp) || at->at_if == (ifp))) \
125 if (n >= ARPTAB_BSIZ) \
131 * Initialize callers source routing table.
134 void init_src_routing(NXHashTable
**sourceRouteTable
)
136 extern NXHashTablePrototype SRTablePrototype
;
137 *sourceRouteTable
= NXCreateHashTable(SRTablePrototype
, 0, NULL
);
141 * Search for a source route (given a destination address).
144 sroute_t
*find_sr(NXHashTable
*sourceRouteTable
, unsigned long idst
)
146 srtable_t
*sourceRouteEntry
= NXHashGet(sourceRouteTable
,
147 (const void *)&idst
);
148 if (sourceRouteEntry
) {
149 return &sourceRouteEntry
->ri
;
155 * Add an entry to the callers source routing table.
158 void add_sr(netif_t netif
, NXHashTable
*sourceRouteTable
, unsigned long ipAddr
,
159 sroute_t
*rip
, unsigned long srLimit
)
161 srtable_t
*sourceRouteEntry
;
162 struct ifnet
*ifp
= (struct ifnet
*)netif
;
164 if ((rip
->rc
.len
> 18)|| (rip
->rc
.len
< 2) || (rip
->rc
.len
& 1))
168 * See if the entry is already in the table
170 sourceRouteEntry
= NXHashGet(sourceRouteTable
,&ipAddr
);
171 if (sourceRouteEntry
) {
172 bcopy(rip
, &sourceRouteEntry
->ri
, rip
->rc
.len
);
173 sourceRouteEntry
->ri
.rc
.bcast
= 0; /* make non-bcast */
174 sourceRouteEntry
->ri
.rc
.dir
= ~sourceRouteEntry
->ri
.rc
.dir
;
179 * See if there's room in the table for another entry.
181 if (NXCountHashTable(sourceRouteTable
) >= srLimit
) {
183 NXHashState state
= NXInitHashState(sourceRouteTable
);
186 * Need to delete an entry.
188 while (NXNextHashState(sourceRouteTable
, &state
,
189 (void **)&sourceRouteEntry
)) {
194 * Look for an entry without a corresponding entry in the
197 ARPTAB_LOOK(at
, sourceRouteEntry
->ipAddr
, ifp
);
200 * Found one - try to remove it
203 NXHashRemove(sourceRouteTable
,
204 (const void *)&sourceRouteEntry
->ipAddr
);
205 if (sourceRouteEntry
) {
206 kfree(sourceRouteEntry
,sizeof(srtable_t
));
212 if (dumpedOne
== NO
) {
213 printf("add_sr: source route table overflow\n");
218 sourceRouteEntry
= (srtable_t
*)kalloc(sizeof(srtable_t
));
220 sourceRouteEntry
->ipAddr
= ipAddr
;
221 bcopy(rip
, &sourceRouteEntry
->ri
, rip
->rc
.len
);
222 sourceRouteEntry
->ri
.rc
.bcast
= 0; /* make non-bcast */
223 sourceRouteEntry
->ri
.rc
.dir
= ~sourceRouteEntry
->ri
.rc
.dir
;
226 NXHashInsert(sourceRouteTable
,(const void *)&sourceRouteEntry
->ipAddr
);
227 if (sourceRouteEntry
) /* shouldn't happen */
228 kfree(sourceRouteEntry
,sizeof(srtable_t
));
232 * Find & return the source route to the callers address.
235 void get_src_route(NXHashTable
*sourceRouteTable
, unsigned long idst
,
236 unsigned char *da
, tokenHeader_t
*th
)
238 sroute_t
*sourceRoute
;
241 return; /* don't handle group addresses */
244 * Find source route in srtable and copy to caller's
245 * tokenHeader_t (or turn off sri bit).
247 sourceRoute
= find_sr(sourceRouteTable
, idst
);
249 bcopy(sourceRoute
, &th
->ri
, sourceRoute
->rc
.len
);
253 th
->sa
[0] &= ~TR_RII
; /* turn off source routing bit */
257 * Save the source route in the callers MAC header.
260 void save_src_route(netif_t netif
, NXHashTable
*sourceRouteTable
,
261 unsigned long ipAddr
, tokenHeader_t
*th
, unsigned long srLimit
)
264 * If frame has a routing field > 2 then save it (i.e. it's been
265 * thru at least one bridge).
267 if ((th
->sa
[0] & TR_RII
) && (th
->ri
.rc
.len
> 2))
268 add_sr(netif
, sourceRouteTable
, ipAddr
, &th
->ri
, srLimit
);
273 * Returns length of the source routing field in callers MAC header.
274 * Returns -1 if the header is invalid.
277 int get_ri_len(tokenHeader_t
*th
)
280 sroute_t
*rif
= (sroute_t
*)&th
->ri
;
282 if (th
->sa
[0] & 0x80) {
283 ri_len
= (int)rif
->rc
.len
;
284 if ((ri_len
& 1) || (ri_len
< 2) || (ri_len
> 18)) {
292 * Returns the length of an 802.5 MAC header (including routing field).
295 int get_8025_hdr_len(tokenHeader_t
*th
)
299 ri_len
= get_ri_len(th
);
301 return ri_len
; // bad header
303 return ri_len
+ MAC_HDR_MIN
;
307 * Returns 1 if mac address is any type of broadcast, zero otherwise.
310 int check_mac_bcast(tokenHeader_t
*th
)
312 if (th
->da
[0] & 0x80)
313 return 1; // group address (I/G bit)
318 * Build a broadcast routing field in the callers MAC header.
321 void make_sr_bcast(tokenHeader_t
*th
, srbcast_t type
)
323 if ((type
== SRB_OFF
) || (type
>= SRB_INVALID
)) {
324 th
->sa
[0] &= ~TR_RII
;
328 th
->sa
[0] |= TR_RII
; /* turn on rii bit to ind. src rtng field */
331 * Build the routing control field for the requested
335 th
->ri
.rc
.bcast
= BI_AR_BCAST
;
337 th
->ri
.rc
.bcast
= BI_SR_BCAST
;
341 th
->ri
.rc
.longf
= LF_BCAST
;
346 * Make the callers MAC header a reply to sender.
349 void make_mac_reply(tokenHeader_t
*th
)
353 * Copy source address to destination address. Turn off RII bit in
354 * the destination address.
356 bcopy(th
->sa
, th
->da
, sizeof(th
->da
));
357 th
->da
[0] &= ~TR_RII
;
360 * Convert the source routing field to a reply (flip direction
361 * bit & turn off broadcast bits).
363 if (th
->sa
[0] & TR_RII
) {
364 th
->ri
.rc
.dir
= ~th
->ri
.rc
.dir
;
370 #endif /* _TOKENSR_ */
372 #endif /* DRIVER_PRIVATE */