136392Ssklower /*********************************************************** 236392Ssklower Copyright IBM Corporation 1987 336392Ssklower 436392Ssklower All Rights Reserved 536392Ssklower 636392Ssklower Permission to use, copy, modify, and distribute this software and its 736392Ssklower documentation for any purpose and without fee is hereby granted, 836392Ssklower provided that the above copyright notice appear in all copies and that 936392Ssklower both that copyright notice and this permission notice appear in 1036392Ssklower supporting documentation, and that the name of IBM not be 1136392Ssklower used in advertising or publicity pertaining to distribution of the 1236392Ssklower software without specific, written prior permission. 1336392Ssklower 1436392Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536392Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636392Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736392Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836392Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936392Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036392Ssklower SOFTWARE. 2136392Ssklower 2236392Ssklower ******************************************************************/ 2336392Ssklower 2436392Ssklower /* 2536392Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636392Ssklower */ 2736392Ssklower /* $Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */ 2836392Ssklower /* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */ 2936392Ssklower 3036392Ssklower #ifndef lint 3136392Ssklower static char *rcsid = "$Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $"; 3236392Ssklower #endif lint 3336392Ssklower 3436392Ssklower #ifdef ISO 3536392Ssklower 3637469Ssklower #include "types.h" 3737469Ssklower #include "param.h" 38*37551Smckusick #include "../ufs/dir.h" 39*37551Smckusick #include "user.h" 4037469Ssklower #include "mbuf.h" 4137469Ssklower #include "domain.h" 4237469Ssklower #include "protosw.h" 4337469Ssklower #include "socket.h" 4437469Ssklower #include "socketvar.h" 4537469Ssklower #include "errno.h" 4637469Ssklower #include "ioctl.h" 4737469Ssklower #include "kernel.h" 4836392Ssklower 4936392Ssklower #include "../net/if.h" 5036392Ssklower #include "../net/route.h" 5136392Ssklower 5237469Ssklower #include "iso.h" 5337469Ssklower #include "iso_var.h" 5437469Ssklower #include "iso_snpac.h" 5537469Ssklower #include "clnp.h" 5637469Ssklower #include "clnp_stat.h" 5737469Ssklower #include "argo_debug.h" 5837469Ssklower #include "esis.h" 5936392Ssklower 6036392Ssklower #define SNPAC_BSIZ 20 /* bucket size */ 6136392Ssklower #define SNPAC_NB 13 /* number of buckets */ 6236392Ssklower #define SNPAC_SIZE (SNPAC_BSIZ * SNPAC_NB) 6336392Ssklower struct snpa_cache iso_snpac[SNPAC_SIZE]; 6437469Ssklower u_int iso_snpac_size = SNPAC_SIZE;/* for iso_map command */ 6536392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 6636392Ssklower 6737469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 6837469Ssklower extern u_long iso_hashchar(); 6937469Ssklower static struct sockaddr_iso 7037469Ssklower dst = {sizeof(dst), AF_ISO}, 7137469Ssklower gte = {sizeof(dst), AF_ISO}, 7237469Ssklower src = {sizeof(dst), AF_ISO}, 7337469Ssklower msk = {sizeof(dst), AF_ISO}, 7437469Ssklower zmk = {1}; 7537469Ssklower #define zsi blank_siso 7637469Ssklower #define zero_isoa zsi.siso_addr 7737469Ssklower #define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \ 7837469Ssklower ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len))) 7937469Ssklower #define S(x) ((struct sockaddr *)&(x)) 8037469Ssklower 8136392Ssklower #define SNPAC_HASH(addr) \ 8237469Ssklower (((u_long) iso_hashchar((caddr_t)addr, (int)addr->isoa_len)) % SNPAC_NB) 8336392Ssklower 8436392Ssklower #define SNPAC_LOOK(sc,addr) { \ 8536392Ssklower register n; \ 8636392Ssklower sc = &iso_snpac[SNPAC_HASH(addr) * SNPAC_BSIZ]; \ 8736392Ssklower for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) \ 8836392Ssklower if ((sc->sc_flags & SNPA_VALID) && \ 8936392Ssklower (iso_addrmatch1(&sc->sc_nsap, addr))) \ 9036392Ssklower break; \ 9136392Ssklower if (n >= SNPAC_BSIZ) \ 9236392Ssklower sc = 0; \ 9336392Ssklower } 9436392Ssklower 9536392Ssklower struct snpa_cache *snpac_new(); 9636392Ssklower 9736392Ssklower /* 9836392Ssklower * We only keep track of a single IS at a time. 9936392Ssklower */ 10036392Ssklower struct snpa_cache *known_is; 10136392Ssklower 10236392Ssklower /* 10336392Ssklower * Addresses taken from NBS agreements, December 1987. 10436392Ssklower * 10536392Ssklower * These addresses assume on-the-wire transmission of least significant 10636392Ssklower * bit first. This is the method used by 802.3. When these 10736392Ssklower * addresses are passed to the token ring driver, (802.5), they 10836392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 10936392Ssklower * 11036392Ssklower * Furthermore, according to IBM Austin, these addresses are not 11136392Ssklower * true token ring multicast addresses. More work is necessary 11236392Ssklower * to get multicast to work right on token ring. 11336392Ssklower * 11436392Ssklower * Currently, the token ring driver does not handle multicast, so 11536392Ssklower * these addresses are converted into the broadcast address in 11636392Ssklower * lan_output() That means that if these multicast addresses change 11736392Ssklower * the token ring driver must be altered. 11836392Ssklower */ 11936392Ssklower struct snpa_cache all_es = { 12036392Ssklower { { 0x0 }, /* sc_nsap */ 12136392Ssklower 6, /* sc_len */ 12236392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }, /* sc_snpa */ 12336392Ssklower SNPA_VALID, /* sc_flags */ 12436392Ssklower 0 } /* sc_ht */ 12536392Ssklower }; 12636392Ssklower struct snpa_cache all_is = { 12736392Ssklower { { 0x0 }, /* sc_nsap */ 12836392Ssklower 6, /* sc_len */ 12936392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }, /* sc_snpa */ 13036392Ssklower SNPA_VALID, /* sc_flags */ 13136392Ssklower 0 } /* sc_ht */ 13236392Ssklower }; 13336392Ssklower 13436392Ssklower 13536392Ssklower /* 13636392Ssklower * FUNCTION: iso_snparesolve 13736392Ssklower * 13836392Ssklower * PURPOSE: Resolve an iso address into snpa address 13936392Ssklower * 14036392Ssklower * RETURNS: 0 if addr is resolved 14136392Ssklower * errno if addr is unknown 14236392Ssklower * 14336392Ssklower * SIDE EFFECTS: 14436392Ssklower * 14536392Ssklower * NOTES: If an entry is found that matches the address, that 14636392Ssklower * snpa is returned. If no entry is found, but an IS is 14736392Ssklower * known, then the address of the IS is returned. If 14836392Ssklower * neither an address is found that matches or an IS is 14936392Ssklower * known, then the multi-cast address for "all ES" for 15036392Ssklower * this interface is returned. 15136392Ssklower * 15236392Ssklower * NB: the last case described above constitutes the 15336392Ssklower * query configuration function 9542, sec 6.5 15436392Ssklower * A mechanism is needed to prevent this function from 15536392Ssklower * being invoked if the system is an IS. 15636392Ssklower */ 15737469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 15836392Ssklower struct ifnet *ifp; /* outgoing interface */ 15937469Ssklower struct sockaddr_iso *dest; /* destination */ 16036392Ssklower char *snpa; /* RESULT: snpa to be used */ 16136392Ssklower int *snpa_len; /* RESULT: length of snpa */ 16236392Ssklower { 16336392Ssklower extern struct ifnet loif; /* loopback interface */ 16436392Ssklower struct snpa_cache *sc; /* ptr to snpa table entry */ 16536392Ssklower struct iso_addr *destiso; /* destination iso addr */ 16636392Ssklower 16737469Ssklower destiso = &dest->siso_addr; 16836392Ssklower 16936392Ssklower /* 17036392Ssklower * This hack allows us to send esis packets that have the destination snpa 17136392Ssklower * addresss embedded in the destination nsap address 17236392Ssklower */ 17337469Ssklower if (destiso->isoa_genaddr[0] == AFI_SNA) { 17436392Ssklower /* 17536392Ssklower * This is a subnetwork address. Return it immediately 17636392Ssklower */ 17736392Ssklower IFDEBUG(D_SNPA) 17836392Ssklower printf("iso_snparesolve: return SN address\n"); 17936392Ssklower ENDDEBUG 18036392Ssklower 18136392Ssklower *snpa_len = destiso->isoa_len - 1; /* subtract size of AFI */ 18237469Ssklower bcopy((caddr_t) destiso->isoa_genaddr + 1, (caddr_t)snpa, 18337469Ssklower (unsigned)*snpa_len); 18436392Ssklower return (0); 18536392Ssklower } 18636392Ssklower 18736392Ssklower IFDEBUG(D_SNPA) 18836392Ssklower printf("iso_snparesolve: resolving %s\n", clnp_iso_addrp(destiso)); 18936392Ssklower ENDDEBUG 19036392Ssklower 19136392Ssklower /* 19236392Ssklower * packet is not for us, check cache for an entry 19336392Ssklower */ 19436392Ssklower SNPAC_LOOK(sc, destiso); 19536392Ssklower if (sc == 0) { /* not found */ 19636392Ssklower /* If we are an IS, we can't do much with the packet */ 19736392Ssklower if (iso_systype == SNPA_IS) 19836392Ssklower goto bad; 19936392Ssklower 20036392Ssklower /* 20136392Ssklower * Check if we know about an IS 20236392Ssklower */ 20336392Ssklower if ((known_is) && (known_is->sc_flags & SNPA_VALID)) { 20436392Ssklower sc = known_is; 20536392Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 20636392Ssklower /* 20736392Ssklower * no IS, no match. Return "all es" multicast address for this 20836392Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 20936392Ssklower * 21036392Ssklower * Note: there is a potential problem here. If the destination 21136392Ssklower * is on the subnet and it does not respond with a ESH, but 21236392Ssklower * does send back a TP CC, a connection could be established 21336392Ssklower * where we always transmit the CLNP packet to "all es" 21436392Ssklower */ 21536392Ssklower sc = &all_es; 21636392Ssklower } else { 21736392Ssklower goto bad; 21836392Ssklower } 21936392Ssklower } 22036392Ssklower 22136392Ssklower bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 22236392Ssklower *snpa_len = sc->sc_len; 22336392Ssklower return (0); 22436392Ssklower 22536392Ssklower bad: 22636392Ssklower return(ENETUNREACH); 22736392Ssklower } 22836392Ssklower 22936392Ssklower 23036392Ssklower /* 23136392Ssklower * FUNCTION: snpac_look 23236392Ssklower * 23336392Ssklower * PURPOSE: Look up an entry in the snpa cache 23436392Ssklower * 23536392Ssklower * RETURNS: Pointer to snpa_cache structure, or null 23636392Ssklower * 23736392Ssklower * SIDE EFFECTS: 23836392Ssklower * 23936392Ssklower * NOTES: This is simply SNPAC_LOOK as a procedure. 24036392Ssklower */ 24136392Ssklower struct snpa_cache * 24236392Ssklower snpac_look(isoa) 24336392Ssklower struct iso_addr *isoa; /* destination nsap */ 24436392Ssklower { 24536392Ssklower struct snpa_cache *sc; 24636392Ssklower int s = splimp(); 24736392Ssklower 24836392Ssklower SNPAC_LOOK(sc, isoa); 24936392Ssklower 25036392Ssklower splx(s); 25136392Ssklower return(sc); 25236392Ssklower } 25336392Ssklower 25436392Ssklower /* 25536392Ssklower * FUNCTION: iso_8208snparesolve 25636392Ssklower * 25736392Ssklower * PURPOSE: Find the X.121 address that corresponds to an NSAP addr 25836392Ssklower * 25936392Ssklower * RETURNS: 0 or unix errno 26036392Ssklower * 26136392Ssklower * SIDE EFFECTS: 26236392Ssklower * 26336392Ssklower * NOTES: This ought to invoke the 8208 ES-IS function 26436392Ssklower */ 26537469Ssklower iso_8208snparesolve(dest, snpa, snpa_len) 26637469Ssklower struct sockaddr_iso *dest; /* destination */ 26736392Ssklower char *snpa; /* RESULT: snpa to be used */ 26836392Ssklower int *snpa_len; /* RESULT: length of snpa */ 26936392Ssklower { 27036392Ssklower struct snpa_cache *sc; /* ptr to snpa table entry */ 27136392Ssklower struct iso_addr *destiso; /* destination iso addr */ 27236392Ssklower int s; 27336392Ssklower int err = 0; 27436392Ssklower 27537469Ssklower destiso = &dest->siso_addr; 27636392Ssklower 27736392Ssklower s = splimp(); 27836392Ssklower SNPAC_LOOK(sc, destiso); 27936392Ssklower if (sc) { 28036392Ssklower bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 28136392Ssklower *snpa_len = sc->sc_len; 28236392Ssklower } else { 28336392Ssklower err = ENETUNREACH; 28436392Ssklower } 28536392Ssklower splx(s); 28636392Ssklower return (err); 28736392Ssklower } 28836392Ssklower 28936392Ssklower /* 29036392Ssklower * FUNCTION: iso_8208snpaadd 29136392Ssklower * 29236392Ssklower * PURPOSE: Add an entry to the snpa cache 29336392Ssklower * 29436392Ssklower * RETURNS: 29536392Ssklower * 29636392Ssklower * SIDE EFFECTS: 29736392Ssklower * 29836392Ssklower * NOTES: used by cons 29936392Ssklower */ 30036392Ssklower iso_8208snpaadd(ifp, nsap, snpa, snpalen, ht) 30136392Ssklower struct ifnet *ifp; /* interface info is related to */ 30236392Ssklower struct iso_addr *nsap; /* nsap to add */ 30336392Ssklower caddr_t snpa; /* translation */ 30436392Ssklower int snpalen; /* length in bytes */ 30536392Ssklower short ht; /* holding time (in seconds) */ 30636392Ssklower { 30737469Ssklower snpac_add(ifp, nsap, snpa, snpalen, SNPA_ES, (u_short)ht); 30836392Ssklower } 30936392Ssklower 31036392Ssklower /* 31136392Ssklower * FUNCTION: iso_8208snpadelete 31236392Ssklower * 31336392Ssklower * PURPOSE: Delete an entry from the snpa cache 31436392Ssklower * 31536392Ssklower * RETURNS: nothing 31636392Ssklower * 31736392Ssklower * SIDE EFFECTS: 31836392Ssklower * 31936392Ssklower * NOTES: used by CONS 32036392Ssklower */ 32136392Ssklower iso_8208snpadelete(nsap) 32236392Ssklower struct iso_addr *nsap; 32336392Ssklower { 32436392Ssklower struct snpa_cache *sc = snpac_look(nsap); 32536392Ssklower 32636392Ssklower if (sc != NULL) 32736392Ssklower snpac_free(sc); 32836392Ssklower } 32936392Ssklower 33036392Ssklower /* 33136392Ssklower * FUNCTION: snpac_new 33236392Ssklower * 33336392Ssklower * PURPOSE: create a new entry in the iso address to ethernet 33436392Ssklower * address table 33536392Ssklower * 33636392Ssklower * RETURNS: pointer to newest entry 33736392Ssklower * 33836392Ssklower * SIDE EFFECTS: times out old entries if no new entries are found 33936392Ssklower * 34036392Ssklower * NOTES: If the bucket is full, then timeout the oldest entry 34136392Ssklower * (ie. the one with the youngest holding time) 34236392Ssklower */ 34336392Ssklower struct snpa_cache * 34436392Ssklower snpac_new(isoa) 34536392Ssklower struct iso_addr *isoa; /* iso address to enter into table */ 34636392Ssklower { 34736392Ssklower register struct snpa_cache *sc; 34836392Ssklower register int n; 34936392Ssklower int smallest_ht = 1000000; 35036392Ssklower struct snpa_cache *maybe; 35136392Ssklower 35236392Ssklower sc = &iso_snpac[SNPAC_HASH(isoa) * SNPAC_BSIZ]; 35336392Ssklower for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) { 35436392Ssklower 35536392Ssklower IFDEBUG (D_IOCTL) 35636392Ssklower printf("snpac_new: sc x%x ", sc); 35736392Ssklower 35836392Ssklower if (sc->sc_flags & SNPA_VALID) { 35936392Ssklower int i; 36036392Ssklower 36136392Ssklower printf("(valid) %s ", clnp_iso_addrp(&sc->sc_nsap)); 36236392Ssklower for (i=0; i<sc->sc_len; i++) 36336392Ssklower printf("%x%c", sc->sc_snpa[i], i < (sc->sc_len-1) ? ':' 36436392Ssklower : '\n'); 36536392Ssklower } else { 36636392Ssklower printf("invalid\n"); 36736392Ssklower } 36836392Ssklower ENDDEBUG 36936392Ssklower 37036392Ssklower if (sc->sc_flags & SNPA_VALID) { 37136392Ssklower if (sc->sc_ht < smallest_ht) { 37236392Ssklower smallest_ht = sc->sc_ht; 37336392Ssklower maybe = sc; 37436392Ssklower } 37536392Ssklower } else { 37636392Ssklower return sc; /* found unused slot */ 37736392Ssklower } 37836392Ssklower } 37936392Ssklower snpac_free(maybe); 38036392Ssklower return maybe; 38136392Ssklower } 38236392Ssklower /* 38336392Ssklower * FUNCTION: snpac_free 38436392Ssklower * 38536392Ssklower * PURPOSE: free an entry in the iso address map table 38636392Ssklower * 38736392Ssklower * RETURNS: nothing 38836392Ssklower * 38936392Ssklower * SIDE EFFECTS: 39036392Ssklower * 39136392Ssklower * NOTES: If there is a route entry associated with cache 39236392Ssklower * entry, then delete that as well 39336392Ssklower */ 39436392Ssklower snpac_free(sc) 39536392Ssklower register struct snpa_cache *sc; /* entry to free */ 39636392Ssklower { 39737469Ssklower register struct rtentry *rt; 39837469Ssklower register struct iso_addr *r; 39936392Ssklower 40036392Ssklower if (known_is == sc) { 40136392Ssklower known_is = NULL; 40236392Ssklower } 40337469Ssklower if (sc->sc_rt) { 40437469Ssklower zap_isoaddr(dst, (&(sc->sc_da))); 40537469Ssklower rt = rtalloc1((struct sockaddr *)&dst, 0); 40637469Ssklower if ((sc->sc_rt == rt) && (rt->rt_flags & RTF_UP) 40737469Ssklower && (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 40837469Ssklower RTFREE(rt); 40937469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 41037469Ssklower rt->rt_flags, (struct rtentry **)0); 41137469Ssklower } 41237469Ssklower RTFREE(rt); 41336392Ssklower } 41436392Ssklower bzero((caddr_t)sc, sizeof(struct snpa_cache)); 41536392Ssklower } 41636392Ssklower 41736392Ssklower /* 41836392Ssklower * FUNCTION: snpac_add 41936392Ssklower * 42036392Ssklower * PURPOSE: Add an entry to the snpa cache 42136392Ssklower * 42236392Ssklower * RETURNS: 42336392Ssklower * 42436392Ssklower * SIDE EFFECTS: 42536392Ssklower * 42636392Ssklower * NOTES: If entry already exists, then update holding time. 42736392Ssklower */ 42836392Ssklower snpac_add(ifp, nsap, snpa, snpalen, type, ht) 42936392Ssklower struct ifnet *ifp; /* interface info is related to */ 43036392Ssklower struct iso_addr *nsap; /* nsap to add */ 43136392Ssklower caddr_t snpa; /* translation */ 43237469Ssklower int snpalen; /* translation length */ 43336392Ssklower char type; /* SNPA_IS or SNPA_ES */ 43437469Ssklower u_short ht; /* holding time (in seconds) */ 43536392Ssklower { 43636392Ssklower struct snpa_cache *sc; 43736392Ssklower 43836392Ssklower SNPAC_LOOK(sc, nsap); 43936392Ssklower if (sc == NULL) { 44036392Ssklower sc = snpac_new(nsap); 44136392Ssklower sc->sc_nsap = *nsap; 44236392Ssklower } 44336392Ssklower 44436392Ssklower sc->sc_ht = ht; 44536392Ssklower 44636392Ssklower sc->sc_len = min(snpalen, MAX_SNPALEN); 44737469Ssklower bcopy(snpa, (caddr_t)sc->sc_snpa, sc->sc_len); 44836392Ssklower sc->sc_flags = SNPA_VALID | type; 44936392Ssklower sc->sc_ifp = ifp; 45036392Ssklower 45136392Ssklower if (type & SNPA_IS) 45236392Ssklower snpac_logdefis(sc); 45336392Ssklower } 45436392Ssklower 45536392Ssklower /* 45636392Ssklower * FUNCTION: snpac_ioctl 45736392Ssklower * 45836392Ssklower * PURPOSE: handle ioctls to change the iso address map 45936392Ssklower * 46036392Ssklower * RETURNS: unix error code 46136392Ssklower * 46236392Ssklower * SIDE EFFECTS: changes the snpa_cache table declared above. 46336392Ssklower * 46436392Ssklower * NOTES: 46536392Ssklower */ 46636392Ssklower snpac_ioctl(cmd, data) 46736392Ssklower int cmd; /* ioctl to process */ 46836392Ssklower caddr_t data; /* data for the cmd */ 46936392Ssklower { 47036392Ssklower register struct snpa_req *rq = (struct snpa_req *)data; 47136392Ssklower register struct snpa_cache *sc; 47236392Ssklower register struct iso_addr *isoa; 47336392Ssklower int s; 47437469Ssklower char *type; 47536392Ssklower 47637469Ssklower switch(cmd) { 47737469Ssklower case SIOCSISOMAP: type = "set"; break; 47837469Ssklower case SIOCDISOMAP: type = "delete"; break; 47937469Ssklower case SIOCGISOMAP: type = "get"; break; 48037469Ssklower default: return(snpac_systype(cmd, data)); 48137469Ssklower } 48236392Ssklower 48336392Ssklower /* sanity check */ 48436392Ssklower if (rq->sr_len > MAX_SNPALEN) 48536392Ssklower return(EINVAL); 48636392Ssklower 48736392Ssklower IFDEBUG (D_IOCTL) 48836392Ssklower int i; 48936392Ssklower 49037469Ssklower printf("snpac_ioctl: %s %s to ", type, clnp_iso_addrp(isoa)); 49136392Ssklower for (i=0; i<rq->sr_len; i++) 49236392Ssklower printf("%x%c", rq->sr_snpa[i], i < (rq->sr_len-1) ? ':' : '\n'); 49336392Ssklower ENDDEBUG 49436392Ssklower 49537469Ssklower /* look up this address in table */ 49637469Ssklower isoa = &rq->sr_isoa; 49737469Ssklower 49836392Ssklower SNPAC_LOOK(sc, isoa); 49936392Ssklower if (sc == NULL) { /* not found */ 50036392Ssklower if (cmd != SIOCSISOMAP) 50136392Ssklower return(ENXIO); 50236392Ssklower } 50336392Ssklower 50436392Ssklower switch(cmd) { 50536392Ssklower case SIOCSISOMAP: /* set entry */ 50637469Ssklower snpac_add((struct ifnet *)NULL, isoa, (caddr_t)rq->sr_snpa, 50737469Ssklower (int)rq->sr_len, 50837469Ssklower (char)(rq->sr_flags & (SNPA_ES|SNPA_IS|SNPA_PERM)), 50937469Ssklower rq->sr_ht); 51036392Ssklower break; 51136392Ssklower 51236392Ssklower case SIOCDISOMAP: /* delete entry */ 51336392Ssklower snpac_free(sc); 51436392Ssklower break; 51536392Ssklower 51636392Ssklower case SIOCGISOMAP: /* get entry */ 51737469Ssklower bcopy((caddr_t)&sc->sc_sr, (caddr_t)rq, sizeof(struct snpa_req)); 51836392Ssklower break; 51936392Ssklower } 52036392Ssklower return(0); 52136392Ssklower } 52236392Ssklower 52336392Ssklower /* 52436392Ssklower * FUNCTION: iso_tryloopback 52536392Ssklower * 52636392Ssklower * PURPOSE: Attempt to use the software loopback interface for pkt 52736392Ssklower * 52836392Ssklower * RETURNS: 0 if packet was sent successfully 52936392Ssklower * errno if there was a problem sending the packet 53036392Ssklower * Ie. the return value of looutput 53136392Ssklower * -1 if software loopback is not appropriate 53236392Ssklower * 53336392Ssklower * SIDE EFFECTS: 53436392Ssklower * 53536392Ssklower * NOTES: 53636392Ssklower */ 53737469Ssklower iso_tryloopback(m, dest) 53836392Ssklower struct mbuf *m; /* pkt */ 53937469Ssklower struct sockaddr_iso *dest; /* destination */ 54036392Ssklower { 54136392Ssklower struct iso_addr *destiso; /* destination iso addr */ 54236392Ssklower 54337469Ssklower destiso = &dest->siso_addr; 54436392Ssklower 54536392Ssklower if (clnp_ours(destiso)) { 54636392Ssklower IFDEBUG(D_SNPA) 54736392Ssklower printf("iso_tryloopback: local destination\n"); 54836392Ssklower ENDDEBUG 54936392Ssklower if (loif.if_flags & IFF_UP) { 55036392Ssklower IFDEBUG(D_SNPA) 55136392Ssklower printf("iso_tryloopback: calling looutput\n"); 55236392Ssklower ENDDEBUG 55337469Ssklower return (looutput(&loif, m, (struct sockaddr *)dest)); 55436392Ssklower } 55536392Ssklower } 55636392Ssklower return (-1); 55736392Ssklower } 55836392Ssklower 55936392Ssklower /* 56036392Ssklower * FUNCTION: snpac_systype 56136392Ssklower * 56236392Ssklower * PURPOSE: Set/Get the system type and esis parameters 56336392Ssklower * 56436392Ssklower * RETURNS: 0 on success, or unix error code 56536392Ssklower * 56636392Ssklower * SIDE EFFECTS: 56736392Ssklower * 56836392Ssklower * NOTES: 56936392Ssklower */ 57036392Ssklower snpac_systype (cmd, data) 57136392Ssklower int cmd; /* ioctl to process */ 57236392Ssklower caddr_t data; /* data for the cmd */ 57336392Ssklower { 57436392Ssklower register struct systype_req *rq = (struct systype_req *)data; 57536392Ssklower extern short esis_holding_time, esis_config_time; 57636392Ssklower 57736392Ssklower IFDEBUG (D_IOCTL) 57836392Ssklower if (cmd == SIOCSSTYPE) 57936392Ssklower printf("snpac_systype: cmd set, type x%x, ht %d, ct %d\n", 58036392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 58136392Ssklower else 58236392Ssklower printf("snpac_systype: cmd get\n"); 58336392Ssklower ENDDEBUG 58436392Ssklower 58536392Ssklower if (cmd == SIOCSSTYPE) { 586*37551Smckusick if (suser(u.u_cred, &u.u_acflag)) 58736392Ssklower return(EACCES); 58836392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 58936392Ssklower return(EINVAL); 59036392Ssklower if (rq->sr_type & SNPA_ES) { 59136392Ssklower iso_systype = SNPA_ES; 59236392Ssklower } else if (rq->sr_type & SNPA_IS) { 59336392Ssklower iso_systype = SNPA_IS; 59436392Ssklower } else { 59536392Ssklower return(EINVAL); 59636392Ssklower } 59736392Ssklower esis_holding_time = rq->sr_holdt; 59836392Ssklower esis_config_time = rq->sr_configt; 59936392Ssklower } else if (cmd == SIOCGSTYPE) { 60036392Ssklower rq->sr_type = iso_systype; 60136392Ssklower rq->sr_holdt = esis_holding_time; 60236392Ssklower rq->sr_configt = esis_config_time; 60336392Ssklower } else { 60436392Ssklower return(EINVAL); 60536392Ssklower } 60636392Ssklower return(0); 60736392Ssklower } 60836392Ssklower 60936392Ssklower /* 61036392Ssklower * FUNCTION: snpac_logdefis 61136392Ssklower * 61236392Ssklower * PURPOSE: Mark the IS passed as the default IS 61336392Ssklower * 61436392Ssklower * RETURNS: nothing 61536392Ssklower * 61636392Ssklower * SIDE EFFECTS: 61736392Ssklower * 61836392Ssklower * NOTES: 61936392Ssklower */ 62036392Ssklower snpac_logdefis(sc) 62137469Ssklower register struct snpa_cache *sc; 62236392Ssklower { 62337469Ssklower register struct iso_addr *r; 62437469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 62537469Ssklower if (known_is == 0) 62637469Ssklower known_is = sc; 62737469Ssklower if (known_is != sc) { 62837469Ssklower if (known_is->sc_rt) { 62937469Ssklower rtfree(known_is->sc_rt); 63037469Ssklower known_is->sc_rt = 0; 63137469Ssklower } 63237469Ssklower known_is = sc; 63336392Ssklower } 63437469Ssklower if (rt == 0) { 63537469Ssklower zap_isoaddr(dst, &(sc->sc_nsap)); 63637469Ssklower rtrequest(RTM_ADD, S(zsi), S(dst), S(zmk), 63737469Ssklower RTF_DYNAMIC|RTF_GATEWAY, &sc->sc_rt); 63837469Ssklower return; 63937469Ssklower } 64037469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 64137469Ssklower ((struct sockaddr_iso *)rt->rt_gateway)->siso_addr = sc->sc_nsap; 64237469Ssklower known_is = sc; 64337469Ssklower sc->sc_rt = rt; 64437469Ssklower } 64536392Ssklower } 64636392Ssklower 64736392Ssklower /* 64836392Ssklower * FUNCTION: snpac_age 64936392Ssklower * 65036392Ssklower * PURPOSE: Time out snpac entries 65136392Ssklower * 65236392Ssklower * RETURNS: 65336392Ssklower * 65436392Ssklower * SIDE EFFECTS: 65536392Ssklower * 65636392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 65736392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 65836392Ssklower * if the entry is added a moment before snpac_age is 65936392Ssklower * called, the entry will immediately have SNPAC_AGE 66036392Ssklower * seconds taken off the holding time, even though 66136392Ssklower * it has only been held a brief moment. 66236392Ssklower * 66336392Ssklower * The proper way to do this is set an expiry timeval 66436392Ssklower * equal to current time + holding time. Then snpac_age 66536392Ssklower * would time out entries where expiry date is older 66636392Ssklower * than the current time. 66736392Ssklower */ 66836392Ssklower snpac_age() 66936392Ssklower { 67036392Ssklower register struct snpa_cache *sc; 67136392Ssklower register int i; 67236392Ssklower 67336392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 67436392Ssklower 67536392Ssklower sc = &iso_snpac[0]; 67636392Ssklower for (i=0; i<SNPAC_SIZE; i++, sc++) { 67736392Ssklower if (((sc->sc_flags & SNPA_PERM) == 0) && (sc->sc_flags & SNPA_VALID)) { 67836392Ssklower sc->sc_ht -= SNPAC_AGE; 67936392Ssklower if (sc->sc_ht > 0) 68036392Ssklower continue; 68136392Ssklower else 68236392Ssklower snpac_free(sc); 68336392Ssklower } 68436392Ssklower } 68536392Ssklower } 68636392Ssklower 68736392Ssklower /* 68836392Ssklower * FUNCTION: snpac_ownmulti 68936392Ssklower * 69036392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 69136392Ssklower * of the same type as the system. 69236392Ssklower * 69336392Ssklower * RETURNS: true or false 69436392Ssklower * 69536392Ssklower * SIDE EFFECTS: 69636392Ssklower * 69736392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 69836392Ssklower * as interm kludge until 69936392Ssklower * real multicast addresses can be configured 70036392Ssklower */ 70136392Ssklower snpac_ownmulti(snpa, len) 70236392Ssklower char *snpa; 70336392Ssklower int len; 70436392Ssklower { 70537469Ssklower return (((iso_systype & SNPA_ES) && 70637469Ssklower (!bcmp((caddr_t)snpa, (caddr_t)all_es.sc_snpa, (unsigned)len))) || 70737469Ssklower ((iso_systype & SNPA_IS) && 70837469Ssklower (!bcmp((caddr_t)snpa, (caddr_t)all_is.sc_snpa, (unsigned)len)))); 70936392Ssklower } 71036392Ssklower 71136392Ssklower /* 71236392Ssklower * FUNCTION: snpac_flushifp 71336392Ssklower * 71436392Ssklower * PURPOSE: Flush entries associated with specific ifp 71536392Ssklower * 71636392Ssklower * RETURNS: nothing 71736392Ssklower * 71836392Ssklower * SIDE EFFECTS: 71936392Ssklower * 72036392Ssklower * NOTES: 72136392Ssklower */ 72236392Ssklower snpac_flushifp(ifp) 72336392Ssklower struct ifnet *ifp; 72436392Ssklower { 72536392Ssklower register struct snpa_cache *sc; 72636392Ssklower register int i; 72736392Ssklower 72836392Ssklower sc = &iso_snpac[0]; 72936392Ssklower for (i=0; i<SNPAC_SIZE; i++, sc++) { 73036392Ssklower if ((sc->sc_ifp == ifp) && (sc->sc_flags & SNPA_VALID)) { 73136392Ssklower snpac_free(sc); 73236392Ssklower } 73336392Ssklower } 73436392Ssklower } 73536392Ssklower 73636392Ssklower /* 73736392Ssklower * FUNCTION: snpac_rtrequest 73836392Ssklower * 73936392Ssklower * PURPOSE: Make a routing request 74036392Ssklower * 74136392Ssklower * RETURNS: nothing 74236392Ssklower * 74336392Ssklower * SIDE EFFECTS: 74436392Ssklower * 74536392Ssklower * NOTES: In the future, this should make a request of a user 74636392Ssklower * level routing daemon. 74736392Ssklower */ 74837469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 74936392Ssklower int req; 75037469Ssklower struct iso_addr *host; 75136392Ssklower struct iso_addr *gateway; 75237469Ssklower struct iso_addr *netmask; 75336392Ssklower short flags; 75437469Ssklower struct rtentry **ret_nrt; 75536392Ssklower { 75637469Ssklower register struct iso_addr *r; 75736392Ssklower 75836392Ssklower IFDEBUG(D_SNPA) 75936392Ssklower printf("snpac_rtrequest: "); 76037469Ssklower if (req == RTM_ADD) 76136392Ssklower printf("add"); 76237469Ssklower else if (req == RTM_DELETE) 76336392Ssklower printf("delete"); 76436392Ssklower else 76536392Ssklower printf("unknown command"); 76637469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 76736392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 76836392Ssklower ENDDEBUG 76936392Ssklower 77036392Ssklower 77137469Ssklower zap_isoaddr(dst, host); 77237469Ssklower zap_isoaddr(gte, gateway); 77337469Ssklower zap_isoaddr(msk, netmask); 77437469Ssklower 77537469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 77637469Ssklower flags, ret_nrt); 77736392Ssklower } 77836392Ssklower 77936392Ssklower /* 78036392Ssklower * FUNCTION: snpac_addrt 78136392Ssklower * 78236392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 78336392Ssklower * 78436392Ssklower * RETURNS: nothing 78536392Ssklower * 78636392Ssklower * SIDE EFFECTS: 78736392Ssklower * 78836392Ssklower * NOTES: If a cache entry exists for gateway, then 78936392Ssklower * make a routing entry (host, gateway) and associate 79036392Ssklower * with gateway. 79136392Ssklower * 79236392Ssklower * If a route already exists and is different, first delete 79336392Ssklower * it. 79436392Ssklower * 79536392Ssklower * This could be made more efficient by checking 79636392Ssklower * the existing route before adding a new one. 79736392Ssklower */ 79837469Ssklower snpac_addrt(host, gateway, source, netmask) 79937469Ssklower struct iso_addr *host, *gateway, *source, *netmask; 80036392Ssklower { 80137469Ssklower register struct snpa_cache *sc; 80237469Ssklower register struct iso_addr *r; 80336392Ssklower 80436392Ssklower SNPAC_LOOK(sc, gateway); 80536392Ssklower if (sc != NULL) { 80637469Ssklower bcopy((caddr_t)host, (caddr_t)&sc->sc_da, sizeof(struct iso_addr)); 80737469Ssklower zap_isoaddr(dst, host); 80837469Ssklower zap_isoaddr(gte, gateway); 80937469Ssklower zap_isoaddr(src, source); 81037469Ssklower zap_isoaddr(msk, netmask); 81137469Ssklower if (netmask) { 81237469Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(src), &sc->sc_rt); 81337469Ssklower } else 81437469Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 81537469Ssklower RTF_DONE | RTF_HOST, S(src), &sc->sc_rt); 81636392Ssklower } 81736392Ssklower } 81836392Ssklower #endif ISO 819