/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* Copyright (c) 1993 NeXT Computer, Inc. All rights reserved. * * tokensr.h - Token-ring IEEE 802.5 source routing utility functions. * * We currently make these functions static inlines. These should * be considered for movement to a library and made public (after * sanitizing API). * * HISTORY * * 22-Jul-94 John Immordino (jimmord) at NeXT * Converted static array of source routes to a hash table. * Loosely coupled hash table entries to arp table entries, ie. * when hash table is full, delete the first entry for which there * is no arp entry before inserting the next source route. * * 26-Apr-94 John Immordino (jimmord) at NeXT * Cleaned up. Fixed byte-swap problems, converted all addresses to * character arrays, etc. * * 07-Apr-93 Joel Greenblatt at NeXT * Created * */ #ifdef DRIVER_PRIVATE #ifndef _TOKENSR_ #define _TOKENSR_ #include #include #include #include #include #include #include /* Not an Obj-C header */ /* * Virtual driver parameters * Used by if_vtrXX modules */ typedef struct { int vunit; int vflags; int vmtu; int vtokpri; } vparms_t; /* * Source routing table entry * Note: ipAddr must be the first element in order for our hash table * code to work properly. */ typedef struct { unsigned long ipAddr; /* IP address of this entry - */ /* needed for our temporary */ /* arp table lookup scheme */ sroute_t ri; /* routing information field */ } srtable_t; /* * Encoded source-routing broadcast type (used as parameter to * source routing routines). */ typedef enum { SRB_OFF, /* no source-route broadcast */ SRB_AR, /* all-routes broadcast */ SRB_SR, /* single-route broadcast */ SRB_INVALID /* invalid entry */ } srbcast_t; /* * ARP code taken from bsd/netinet/if_ether.c. Need this in order * to perform lookups of IP addresses to determine which source route * entry to remove from the table. The first source route entry without * a corresponding ARP entry will be removed. */ #ifdef GATEWAY #define ARPTAB_BSIZ 16 /* bucket size */ #define ARPTAB_NB 37 /* number of buckets */ #else #define ARPTAB_BSIZ 9 /* bucket size */ #define ARPTAB_NB 19 /* number of buckets */ #endif extern struct arptab arptab[]; #define ARPTAB_HASH(a) \ ((u_long)(a) % ARPTAB_NB) /* * Change to permit multiple heterogenous interfaces to co-exist. */ #define ARPTAB_LOOK(at,addr,ifp) { \ register n; \ at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \ for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \ if (at->at_iaddr.s_addr == addr && \ (!(ifp) || at->at_if == (ifp))) \ break; \ if (n >= ARPTAB_BSIZ) \ at = 0; \ } /* * Initialize callers source routing table. */ static __inline__ void init_src_routing(NXHashTable **sourceRouteTable) { extern NXHashTablePrototype SRTablePrototype; *sourceRouteTable = NXCreateHashTable(SRTablePrototype, 0, NULL); } /* * Search for a source route (given a destination address). */ static __inline__ sroute_t *find_sr(NXHashTable *sourceRouteTable, unsigned long idst) { srtable_t *sourceRouteEntry = NXHashGet(sourceRouteTable, (const void *)&idst); if (sourceRouteEntry) { return &sourceRouteEntry->ri; } return NULL; } /* * Add an entry to the callers source routing table. */ static __inline__ void add_sr(netif_t netif, NXHashTable *sourceRouteTable, unsigned long ipAddr, sroute_t *rip, unsigned long srLimit) { srtable_t *sourceRouteEntry; struct ifnet *ifp = (struct ifnet *)netif; if ((rip->rc.len > 18)|| (rip->rc.len < 2) || (rip->rc.len & 1)) return; /* * See if the entry is already in the table */ sourceRouteEntry = NXHashGet(sourceRouteTable,&ipAddr); if (sourceRouteEntry) { bcopy(rip, &sourceRouteEntry->ri, rip->rc.len); sourceRouteEntry->ri.rc.bcast = 0; /* make non-bcast */ sourceRouteEntry->ri.rc.dir = ~sourceRouteEntry->ri.rc.dir; return; } /* * See if there's room in the table for another entry. */ if (NXCountHashTable(sourceRouteTable) >= srLimit) { BOOL dumpedOne = NO; NXHashState state = NXInitHashState(sourceRouteTable); /* * Need to delete an entry. */ while (NXNextHashState(sourceRouteTable, &state, (void **)&sourceRouteEntry)) { struct arptab *at; /* * Look for an entry without a corresponding entry in the * arp table. */ ARPTAB_LOOK(at, sourceRouteEntry->ipAddr, ifp); if (at == NULL) { /* * Found one - try to remove it */ sourceRouteEntry = NXHashRemove(sourceRouteTable, (const void *)&sourceRouteEntry->ipAddr); if (sourceRouteEntry) { kfree(sourceRouteEntry,sizeof(srtable_t)); dumpedOne = YES; break; } } } if (dumpedOne == NO) { printf("add_sr: source route table overflow\n"); return; } } sourceRouteEntry = (srtable_t *)kalloc(sizeof(srtable_t)); sourceRouteEntry->ipAddr = ipAddr; bcopy(rip, &sourceRouteEntry->ri, rip->rc.len); sourceRouteEntry->ri.rc.bcast = 0; /* make non-bcast */ sourceRouteEntry->ri.rc.dir = ~sourceRouteEntry->ri.rc.dir; sourceRouteEntry = NXHashInsert(sourceRouteTable,(const void *)&sourceRouteEntry->ipAddr); if (sourceRouteEntry) /* shouldn't happen */ kfree(sourceRouteEntry,sizeof(srtable_t)); } /* * Find & return the source route to the callers address. */ static __inline__ void get_src_route(NXHashTable *sourceRouteTable, unsigned long idst, unsigned char *da, tokenHeader_t *th) { sroute_t *sourceRoute; if (da[0] & 0x80) return; /* don't handle group addresses */ /* * Find source route in srtable and copy to caller's * tokenHeader_t (or turn off sri bit). */ sourceRoute = find_sr(sourceRouteTable, idst); if (sourceRoute) { bcopy(sourceRoute, &th->ri, sourceRoute->rc.len); th->sa[0] |= TR_RII; } else th->sa[0] &= ~TR_RII; /* turn off source routing bit */ } /* * Save the source route in the callers MAC header. */ static __inline__ void save_src_route(netif_t netif, NXHashTable *sourceRouteTable, unsigned long ipAddr, tokenHeader_t *th, unsigned long srLimit) { /* * If frame has a routing field > 2 then save it (i.e. it's been * thru at least one bridge). */ if ((th->sa[0] & TR_RII) && (th->ri.rc.len > 2)) add_sr(netif, sourceRouteTable, ipAddr, &th->ri, srLimit); } /* * Returns length of the source routing field in callers MAC header. * Returns -1 if the header is invalid. */ static __inline__ int get_ri_len(tokenHeader_t *th) { int ri_len = 0; sroute_t *rif = (sroute_t *)&th->ri; if (th->sa[0] & 0x80) { ri_len = (int)rif->rc.len; if ((ri_len & 1) || (ri_len < 2) || (ri_len > 18)) { ri_len = -1; } } return ri_len; } /* * Returns the length of an 802.5 MAC header (including routing field). */ static __inline__ int get_8025_hdr_len(tokenHeader_t *th) { int ri_len; ri_len = get_ri_len(th); if (ri_len < 0) return ri_len; // bad header return ri_len + MAC_HDR_MIN; } /* * Returns 1 if mac address is any type of broadcast, zero otherwise. */ static __inline__ int check_mac_bcast(tokenHeader_t *th) { if (th->da[0] & 0x80) return 1; // group address (I/G bit) return 0; } /* * Build a broadcast routing field in the callers MAC header. */ static __inline__ void make_sr_bcast(tokenHeader_t *th, srbcast_t type) { if ((type == SRB_OFF) || (type >= SRB_INVALID)) { th->sa[0] &= ~TR_RII; return; } th->sa[0] |= TR_RII; /* turn on rii bit to ind. src rtng field */ /* * Build the routing control field for the requested * broadcast type. */ if (type == SRB_AR) th->ri.rc.bcast = BI_AR_BCAST; else th->ri.rc.bcast = BI_SR_BCAST; th->ri.rc.len = 2; th->ri.rc.dir = 0; th->ri.rc.longf = LF_BCAST; th->ri.rc.rsrvd = 0; } /* * Make the callers MAC header a reply to sender. */ static __inline__ void make_mac_reply(tokenHeader_t *th) { /* * Copy source address to destination address. Turn off RII bit in * the destination address. */ bcopy(th->sa, th->da, sizeof(th->da)); th->da[0] &= ~TR_RII; /* * Convert the source routing field to a reply (flip direction * bit & turn off broadcast bits). */ if (th->sa[0] & TR_RII) { th->ri.rc.dir = ~th->ri.rc.dir; th->ri.rc.bcast = 0; } } #endif /* _TOKENSR_ */ #endif /* DRIVER_PRIVATE */