|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1993 NeXT Computer, Inc. All rights reserved.
26: *
27: * tokensr.h - Token-ring IEEE 802.5 source routing utility functions.
28: *
29: * We currently make these functions static inlines. These should
30: * be considered for movement to a library and made public (after
31: * sanitizing API).
32: *
33: * HISTORY
34: *
35: * 22-Jul-94 John Immordino (jimmord) at NeXT
36: * Converted static array of source routes to a hash table.
37: * Loosely coupled hash table entries to arp table entries, ie.
38: * when hash table is full, delete the first entry for which there
39: * is no arp entry before inserting the next source route.
40: *
41: * 26-Apr-94 John Immordino (jimmord) at NeXT
42: * Cleaned up. Fixed byte-swap problems, converted all addresses to
43: * character arrays, etc.
44: *
45: * 07-Apr-93 Joel Greenblatt at NeXT
46: * Created
47: *
48: */
49:
50: #ifdef DRIVER_PRIVATE
51:
52: #ifndef _TOKENSR_
53: #define _TOKENSR_
54:
55: #import <sys/socket.h>
56: #import <net/tokendefs.h>
57: #import <net/if.h>
58: #import <net/if_arp.h>
59: #import <netinet/in.h>
60: #import <netinet/if_ether.h>
61: #import <objc/hashtable.h> /* Not an Obj-C header */
62:
63: /*
64: * Virtual driver parameters
65: * Used by if_vtrXX modules
66: */
67: typedef struct {
68: int vunit;
69: int vflags;
70: int vmtu;
71: int vtokpri;
72: } vparms_t;
73:
74:
75: /*
76: * Source routing table entry
77: * Note: ipAddr must be the first element in order for our hash table
78: * code to work properly.
79: */
80: typedef struct {
81: unsigned long ipAddr; /* IP address of this entry - */
82: /* needed for our temporary */
83: /* arp table lookup scheme */
84: sroute_t ri; /* routing information field */
85: } srtable_t;
86:
87:
88: /*
89: * Encoded source-routing broadcast type (used as parameter to
90: * source routing routines).
91: */
92: typedef enum {
93: SRB_OFF, /* no source-route broadcast */
94: SRB_AR, /* all-routes broadcast */
95: SRB_SR, /* single-route broadcast */
96: SRB_INVALID /* invalid entry */
97: } srbcast_t;
98:
99: /*
100: * ARP code taken from bsd/netinet/if_ether.c. Need this in order
101: * to perform lookups of IP addresses to determine which source route
102: * entry to remove from the table. The first source route entry without
103: * a corresponding ARP entry will be removed.
104: */
105: #ifdef GATEWAY
106: #define ARPTAB_BSIZ 16 /* bucket size */
107: #define ARPTAB_NB 37 /* number of buckets */
108: #else
109: #define ARPTAB_BSIZ 9 /* bucket size */
110: #define ARPTAB_NB 19 /* number of buckets */
111: #endif
112:
113: extern struct arptab arptab[];
114:
115: #define ARPTAB_HASH(a) \
116: ((u_long)(a) % ARPTAB_NB)
117:
118: /*
119: * Change to permit multiple heterogenous interfaces to co-exist.
120: */
121: #define ARPTAB_LOOK(at,addr,ifp) { \
122: register n; \
123: at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \
124: for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
125: if (at->at_iaddr.s_addr == addr && \
126: (!(ifp) || at->at_if == (ifp))) \
127: break; \
128: if (n >= ARPTAB_BSIZ) \
129: at = 0; \
130: }
131:
132:
133: /*
134: * Initialize callers source routing table.
135: */
136: static __inline__
137: void init_src_routing(NXHashTable **sourceRouteTable)
138: {
139: extern NXHashTablePrototype SRTablePrototype;
140: *sourceRouteTable = NXCreateHashTable(SRTablePrototype, 0, NULL);
141: }
142:
143: /*
144: * Search for a source route (given a destination address).
145: */
146: static __inline__
147: sroute_t *find_sr(NXHashTable *sourceRouteTable, unsigned long idst)
148: {
149: srtable_t *sourceRouteEntry = NXHashGet(sourceRouteTable,
150: (const void *)&idst);
151: if (sourceRouteEntry) {
152: return &sourceRouteEntry->ri;
153: }
154: return NULL;
155: }
156:
157: /*
158: * Add an entry to the callers source routing table.
159: */
160: static __inline__
161: void add_sr(netif_t netif, NXHashTable *sourceRouteTable, unsigned long ipAddr,
162: sroute_t *rip, unsigned long srLimit)
163: {
164: srtable_t *sourceRouteEntry;
165: struct ifnet *ifp = (struct ifnet *)netif;
166:
167: if ((rip->rc.len > 18)|| (rip->rc.len < 2) || (rip->rc.len & 1))
168: return;
169:
170: /*
171: * See if the entry is already in the table
172: */
173: sourceRouteEntry = NXHashGet(sourceRouteTable,&ipAddr);
174: if (sourceRouteEntry) {
175: bcopy(rip, &sourceRouteEntry->ri, rip->rc.len);
176: sourceRouteEntry->ri.rc.bcast = 0; /* make non-bcast */
177: sourceRouteEntry->ri.rc.dir = ~sourceRouteEntry->ri.rc.dir;
178: return;
179: }
180:
181: /*
182: * See if there's room in the table for another entry.
183: */
184: if (NXCountHashTable(sourceRouteTable) >= srLimit) {
185: BOOL dumpedOne = NO;
186: NXHashState state = NXInitHashState(sourceRouteTable);
187:
188: /*
189: * Need to delete an entry.
190: */
191: while (NXNextHashState(sourceRouteTable, &state,
192: (void **)&sourceRouteEntry)) {
193:
194: struct arptab *at;
195:
196: /*
197: * Look for an entry without a corresponding entry in the
198: * arp table.
199: */
200: ARPTAB_LOOK(at, sourceRouteEntry->ipAddr, ifp);
201: if (at == NULL) {
202: /*
203: * Found one - try to remove it
204: */
205: sourceRouteEntry =
206: NXHashRemove(sourceRouteTable,
207: (const void *)&sourceRouteEntry->ipAddr);
208: if (sourceRouteEntry) {
209: kfree(sourceRouteEntry,sizeof(srtable_t));
210: dumpedOne = YES;
211: break;
212: }
213: }
214: }
215: if (dumpedOne == NO) {
216: printf("add_sr: source route table overflow\n");
217: return;
218: }
219: }
220:
221: sourceRouteEntry = (srtable_t *)kalloc(sizeof(srtable_t));
222:
223: sourceRouteEntry->ipAddr = ipAddr;
224: bcopy(rip, &sourceRouteEntry->ri, rip->rc.len);
225: sourceRouteEntry->ri.rc.bcast = 0; /* make non-bcast */
226: sourceRouteEntry->ri.rc.dir = ~sourceRouteEntry->ri.rc.dir;
227:
228: sourceRouteEntry =
229: NXHashInsert(sourceRouteTable,(const void *)&sourceRouteEntry->ipAddr);
230: if (sourceRouteEntry) /* shouldn't happen */
231: kfree(sourceRouteEntry,sizeof(srtable_t));
232: }
233:
234: /*
235: * Find & return the source route to the callers address.
236: */
237: static __inline__
238: void get_src_route(NXHashTable *sourceRouteTable, unsigned long idst,
239: unsigned char *da, tokenHeader_t *th)
240: {
241: sroute_t *sourceRoute;
242:
243: if (da[0] & 0x80)
244: return; /* don't handle group addresses */
245:
246: /*
247: * Find source route in srtable and copy to caller's
248: * tokenHeader_t (or turn off sri bit).
249: */
250: sourceRoute = find_sr(sourceRouteTable, idst);
251: if (sourceRoute) {
252: bcopy(sourceRoute, &th->ri, sourceRoute->rc.len);
253: th->sa[0] |= TR_RII;
254: }
255: else
256: th->sa[0] &= ~TR_RII; /* turn off source routing bit */
257: }
258:
259: /*
260: * Save the source route in the callers MAC header.
261: */
262: static __inline__
263: void save_src_route(netif_t netif, NXHashTable *sourceRouteTable,
264: unsigned long ipAddr, tokenHeader_t *th, unsigned long srLimit)
265: {
266: /*
267: * If frame has a routing field > 2 then save it (i.e. it's been
268: * thru at least one bridge).
269: */
270: if ((th->sa[0] & TR_RII) && (th->ri.rc.len > 2))
271: add_sr(netif, sourceRouteTable, ipAddr, &th->ri, srLimit);
272: }
273:
274:
275: /*
276: * Returns length of the source routing field in callers MAC header.
277: * Returns -1 if the header is invalid.
278: */
279: static __inline__
280: int get_ri_len(tokenHeader_t *th)
281: {
282: int ri_len = 0;
283: sroute_t *rif = (sroute_t *)&th->ri;
284:
285: if (th->sa[0] & 0x80) {
286: ri_len = (int)rif->rc.len;
287: if ((ri_len & 1) || (ri_len < 2) || (ri_len > 18)) {
288: ri_len = -1;
289: }
290: }
291: return ri_len;
292: }
293:
294: /*
295: * Returns the length of an 802.5 MAC header (including routing field).
296: */
297: static __inline__
298: int get_8025_hdr_len(tokenHeader_t *th)
299: {
300: int ri_len;
301:
302: ri_len = get_ri_len(th);
303: if (ri_len < 0)
304: return ri_len; // bad header
305:
306: return ri_len + MAC_HDR_MIN;
307: }
308:
309: /*
310: * Returns 1 if mac address is any type of broadcast, zero otherwise.
311: */
312: static __inline__
313: int check_mac_bcast(tokenHeader_t *th)
314: {
315: if (th->da[0] & 0x80)
316: return 1; // group address (I/G bit)
317: return 0;
318: }
319:
320: /*
321: * Build a broadcast routing field in the callers MAC header.
322: */
323: static __inline__
324: void make_sr_bcast(tokenHeader_t *th, srbcast_t type)
325: {
326: if ((type == SRB_OFF) || (type >= SRB_INVALID)) {
327: th->sa[0] &= ~TR_RII;
328: return;
329: }
330:
331: th->sa[0] |= TR_RII; /* turn on rii bit to ind. src rtng field */
332:
333: /*
334: * Build the routing control field for the requested
335: * broadcast type.
336: */
337: if (type == SRB_AR)
338: th->ri.rc.bcast = BI_AR_BCAST;
339: else
340: th->ri.rc.bcast = BI_SR_BCAST;
341:
342: th->ri.rc.len = 2;
343: th->ri.rc.dir = 0;
344: th->ri.rc.longf = LF_BCAST;
345: th->ri.rc.rsrvd = 0;
346: }
347:
348: /*
349: * Make the callers MAC header a reply to sender.
350: */
351: static __inline__
352: void make_mac_reply(tokenHeader_t *th)
353: {
354:
355: /*
356: * Copy source address to destination address. Turn off RII bit in
357: * the destination address.
358: */
359: bcopy(th->sa, th->da, sizeof(th->da));
360: th->da[0] &= ~TR_RII;
361:
362: /*
363: * Convert the source routing field to a reply (flip direction
364: * bit & turn off broadcast bits).
365: */
366: if (th->sa[0] & TR_RII) {
367: th->ri.rc.dir = ~th->ri.rc.dir;
368: th->ri.rc.bcast = 0;
369: }
370: }
371:
372:
373: #endif /* _TOKENSR_ */
374:
375: #endif /* DRIVER_PRIVATE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.