]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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. | |
11 | * | |
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 | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* Copyright (c) 1993 NeXT Computer, Inc. All rights reserved. | |
23 | * | |
24 | * tokensr.h - Token-ring IEEE 802.5 source routing utility functions. | |
25 | * | |
26 | * We currently make these functions static inlines. These should | |
27 | * be considered for movement to a library and made public (after | |
28 | * sanitizing API). | |
29 | * | |
30 | * HISTORY | |
31 | * | |
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. | |
37 | * | |
38 | * 26-Apr-94 John Immordino (jimmord) at NeXT | |
39 | * Cleaned up. Fixed byte-swap problems, converted all addresses to | |
40 | * character arrays, etc. | |
41 | * | |
42 | * 07-Apr-93 Joel Greenblatt at NeXT | |
43 | * Created | |
44 | * | |
45 | */ | |
46 | ||
47 | #ifdef DRIVER_PRIVATE | |
48 | ||
49 | #ifndef _TOKENSR_ | |
50 | #define _TOKENSR_ | |
51 | ||
52 | #include <sys/socket.h> | |
53 | #include <net/tokendefs.h> | |
54 | #include <net/if.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 */ | |
59 | ||
60 | /* | |
61 | * Virtual driver parameters | |
62 | * Used by if_vtrXX modules | |
63 | */ | |
64 | typedef struct { | |
65 | int vunit; | |
66 | int vflags; | |
67 | int vmtu; | |
68 | int vtokpri; | |
69 | } vparms_t; | |
70 | ||
71 | ||
72 | /* | |
73 | * Source routing table entry | |
74 | * Note: ipAddr must be the first element in order for our hash table | |
75 | * code to work properly. | |
76 | */ | |
77 | typedef struct { | |
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 */ | |
82 | } srtable_t; | |
83 | ||
84 | ||
85 | /* | |
86 | * Encoded source-routing broadcast type (used as parameter to | |
87 | * source routing routines). | |
88 | */ | |
89 | typedef enum { | |
90 | SRB_OFF, /* no source-route broadcast */ | |
91 | SRB_AR, /* all-routes broadcast */ | |
92 | SRB_SR, /* single-route broadcast */ | |
93 | SRB_INVALID /* invalid entry */ | |
94 | } srbcast_t; | |
95 | ||
96 | /* | |
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. | |
101 | */ | |
102 | #ifdef GATEWAY | |
103 | #define ARPTAB_BSIZ 16 /* bucket size */ | |
104 | #define ARPTAB_NB 37 /* number of buckets */ | |
105 | #else | |
106 | #define ARPTAB_BSIZ 9 /* bucket size */ | |
107 | #define ARPTAB_NB 19 /* number of buckets */ | |
108 | #endif | |
109 | ||
110 | extern struct arptab arptab[]; | |
111 | ||
112 | #define ARPTAB_HASH(a) \ | |
113 | ((u_long)(a) % ARPTAB_NB) | |
114 | ||
115 | /* | |
116 | * Change to permit multiple heterogenous interfaces to co-exist. | |
117 | */ | |
118 | #define ARPTAB_LOOK(at,addr,ifp) { \ | |
119 | register n; \ | |
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))) \ | |
124 | break; \ | |
125 | if (n >= ARPTAB_BSIZ) \ | |
126 | at = 0; \ | |
127 | } | |
128 | ||
129 | ||
130 | /* | |
131 | * Initialize callers source routing table. | |
132 | */ | |
133 | static __inline__ | |
134 | void init_src_routing(NXHashTable **sourceRouteTable) | |
135 | { | |
136 | extern NXHashTablePrototype SRTablePrototype; | |
137 | *sourceRouteTable = NXCreateHashTable(SRTablePrototype, 0, NULL); | |
138 | } | |
139 | ||
140 | /* | |
141 | * Search for a source route (given a destination address). | |
142 | */ | |
143 | static __inline__ | |
144 | sroute_t *find_sr(NXHashTable *sourceRouteTable, unsigned long idst) | |
145 | { | |
146 | srtable_t *sourceRouteEntry = NXHashGet(sourceRouteTable, | |
147 | (const void *)&idst); | |
148 | if (sourceRouteEntry) { | |
149 | return &sourceRouteEntry->ri; | |
150 | } | |
151 | return NULL; | |
152 | } | |
153 | ||
154 | /* | |
155 | * Add an entry to the callers source routing table. | |
156 | */ | |
157 | static __inline__ | |
158 | void add_sr(netif_t netif, NXHashTable *sourceRouteTable, unsigned long ipAddr, | |
159 | sroute_t *rip, unsigned long srLimit) | |
160 | { | |
161 | srtable_t *sourceRouteEntry; | |
162 | struct ifnet *ifp = (struct ifnet *)netif; | |
163 | ||
164 | if ((rip->rc.len > 18)|| (rip->rc.len < 2) || (rip->rc.len & 1)) | |
165 | return; | |
166 | ||
167 | /* | |
168 | * See if the entry is already in the table | |
169 | */ | |
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; | |
175 | return; | |
176 | } | |
177 | ||
178 | /* | |
179 | * See if there's room in the table for another entry. | |
180 | */ | |
181 | if (NXCountHashTable(sourceRouteTable) >= srLimit) { | |
182 | BOOL dumpedOne = NO; | |
183 | NXHashState state = NXInitHashState(sourceRouteTable); | |
184 | ||
185 | /* | |
186 | * Need to delete an entry. | |
187 | */ | |
188 | while (NXNextHashState(sourceRouteTable, &state, | |
189 | (void **)&sourceRouteEntry)) { | |
190 | ||
191 | struct arptab *at; | |
192 | ||
193 | /* | |
194 | * Look for an entry without a corresponding entry in the | |
195 | * arp table. | |
196 | */ | |
197 | ARPTAB_LOOK(at, sourceRouteEntry->ipAddr, ifp); | |
198 | if (at == NULL) { | |
199 | /* | |
200 | * Found one - try to remove it | |
201 | */ | |
202 | sourceRouteEntry = | |
203 | NXHashRemove(sourceRouteTable, | |
204 | (const void *)&sourceRouteEntry->ipAddr); | |
205 | if (sourceRouteEntry) { | |
206 | kfree(sourceRouteEntry,sizeof(srtable_t)); | |
207 | dumpedOne = YES; | |
208 | break; | |
209 | } | |
210 | } | |
211 | } | |
212 | if (dumpedOne == NO) { | |
213 | printf("add_sr: source route table overflow\n"); | |
214 | return; | |
215 | } | |
216 | } | |
217 | ||
218 | sourceRouteEntry = (srtable_t *)kalloc(sizeof(srtable_t)); | |
219 | ||
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; | |
224 | ||
225 | sourceRouteEntry = | |
226 | NXHashInsert(sourceRouteTable,(const void *)&sourceRouteEntry->ipAddr); | |
227 | if (sourceRouteEntry) /* shouldn't happen */ | |
228 | kfree(sourceRouteEntry,sizeof(srtable_t)); | |
229 | } | |
230 | ||
231 | /* | |
232 | * Find & return the source route to the callers address. | |
233 | */ | |
234 | static __inline__ | |
235 | void get_src_route(NXHashTable *sourceRouteTable, unsigned long idst, | |
236 | unsigned char *da, tokenHeader_t *th) | |
237 | { | |
238 | sroute_t *sourceRoute; | |
239 | ||
240 | if (da[0] & 0x80) | |
241 | return; /* don't handle group addresses */ | |
242 | ||
243 | /* | |
244 | * Find source route in srtable and copy to caller's | |
245 | * tokenHeader_t (or turn off sri bit). | |
246 | */ | |
247 | sourceRoute = find_sr(sourceRouteTable, idst); | |
248 | if (sourceRoute) { | |
249 | bcopy(sourceRoute, &th->ri, sourceRoute->rc.len); | |
250 | th->sa[0] |= TR_RII; | |
251 | } | |
252 | else | |
253 | th->sa[0] &= ~TR_RII; /* turn off source routing bit */ | |
254 | } | |
255 | ||
256 | /* | |
257 | * Save the source route in the callers MAC header. | |
258 | */ | |
259 | static __inline__ | |
260 | void save_src_route(netif_t netif, NXHashTable *sourceRouteTable, | |
261 | unsigned long ipAddr, tokenHeader_t *th, unsigned long srLimit) | |
262 | { | |
263 | /* | |
264 | * If frame has a routing field > 2 then save it (i.e. it's been | |
265 | * thru at least one bridge). | |
266 | */ | |
267 | if ((th->sa[0] & TR_RII) && (th->ri.rc.len > 2)) | |
268 | add_sr(netif, sourceRouteTable, ipAddr, &th->ri, srLimit); | |
269 | } | |
270 | ||
271 | ||
272 | /* | |
273 | * Returns length of the source routing field in callers MAC header. | |
274 | * Returns -1 if the header is invalid. | |
275 | */ | |
276 | static __inline__ | |
277 | int get_ri_len(tokenHeader_t *th) | |
278 | { | |
279 | int ri_len = 0; | |
280 | sroute_t *rif = (sroute_t *)&th->ri; | |
281 | ||
282 | if (th->sa[0] & 0x80) { | |
283 | ri_len = (int)rif->rc.len; | |
284 | if ((ri_len & 1) || (ri_len < 2) || (ri_len > 18)) { | |
285 | ri_len = -1; | |
286 | } | |
287 | } | |
288 | return ri_len; | |
289 | } | |
290 | ||
291 | /* | |
292 | * Returns the length of an 802.5 MAC header (including routing field). | |
293 | */ | |
294 | static __inline__ | |
295 | int get_8025_hdr_len(tokenHeader_t *th) | |
296 | { | |
297 | int ri_len; | |
298 | ||
299 | ri_len = get_ri_len(th); | |
300 | if (ri_len < 0) | |
301 | return ri_len; // bad header | |
302 | ||
303 | return ri_len + MAC_HDR_MIN; | |
304 | } | |
305 | ||
306 | /* | |
307 | * Returns 1 if mac address is any type of broadcast, zero otherwise. | |
308 | */ | |
309 | static __inline__ | |
310 | int check_mac_bcast(tokenHeader_t *th) | |
311 | { | |
312 | if (th->da[0] & 0x80) | |
313 | return 1; // group address (I/G bit) | |
314 | return 0; | |
315 | } | |
316 | ||
317 | /* | |
318 | * Build a broadcast routing field in the callers MAC header. | |
319 | */ | |
320 | static __inline__ | |
321 | void make_sr_bcast(tokenHeader_t *th, srbcast_t type) | |
322 | { | |
323 | if ((type == SRB_OFF) || (type >= SRB_INVALID)) { | |
324 | th->sa[0] &= ~TR_RII; | |
325 | return; | |
326 | } | |
327 | ||
328 | th->sa[0] |= TR_RII; /* turn on rii bit to ind. src rtng field */ | |
329 | ||
330 | /* | |
331 | * Build the routing control field for the requested | |
332 | * broadcast type. | |
333 | */ | |
334 | if (type == SRB_AR) | |
335 | th->ri.rc.bcast = BI_AR_BCAST; | |
336 | else | |
337 | th->ri.rc.bcast = BI_SR_BCAST; | |
338 | ||
339 | th->ri.rc.len = 2; | |
340 | th->ri.rc.dir = 0; | |
341 | th->ri.rc.longf = LF_BCAST; | |
342 | th->ri.rc.rsrvd = 0; | |
343 | } | |
344 | ||
345 | /* | |
346 | * Make the callers MAC header a reply to sender. | |
347 | */ | |
348 | static __inline__ | |
349 | void make_mac_reply(tokenHeader_t *th) | |
350 | { | |
351 | ||
352 | /* | |
353 | * Copy source address to destination address. Turn off RII bit in | |
354 | * the destination address. | |
355 | */ | |
356 | bcopy(th->sa, th->da, sizeof(th->da)); | |
357 | th->da[0] &= ~TR_RII; | |
358 | ||
359 | /* | |
360 | * Convert the source routing field to a reply (flip direction | |
361 | * bit & turn off broadcast bits). | |
362 | */ | |
363 | if (th->sa[0] & TR_RII) { | |
364 | th->ri.rc.dir = ~th->ri.rc.dir; | |
365 | th->ri.rc.bcast = 0; | |
366 | } | |
367 | } | |
368 | ||
369 | ||
370 | #endif /* _TOKENSR_ */ | |
371 | ||
372 | #endif /* DRIVER_PRIVATE */ |