|
|
1.1 root 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.