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 36*37469Ssklower #include "types.h" 37*37469Ssklower #include "param.h" 38*37469Ssklower #include "mbuf.h" 39*37469Ssklower #include "domain.h" 40*37469Ssklower #include "protosw.h" 41*37469Ssklower #include "socket.h" 42*37469Ssklower #include "socketvar.h" 43*37469Ssklower #include "errno.h" 44*37469Ssklower #include "ioctl.h" 45*37469Ssklower #include "time.h" 46*37469Ssklower #include "kernel.h" 4736392Ssklower 4836392Ssklower #include "../net/if.h" 4936392Ssklower #include "../net/route.h" 5036392Ssklower 51*37469Ssklower #include "iso.h" 52*37469Ssklower #include "iso_var.h" 53*37469Ssklower #include "iso_snpac.h" 54*37469Ssklower #include "clnp.h" 55*37469Ssklower #include "clnp_stat.h" 56*37469Ssklower #include "argo_debug.h" 57*37469Ssklower #include "esis.h" 5836392Ssklower 5936392Ssklower #define SNPAC_BSIZ 20 /* bucket size */ 6036392Ssklower #define SNPAC_NB 13 /* number of buckets */ 6136392Ssklower #define SNPAC_SIZE (SNPAC_BSIZ * SNPAC_NB) 6236392Ssklower struct snpa_cache iso_snpac[SNPAC_SIZE]; 63*37469Ssklower u_int iso_snpac_size = SNPAC_SIZE;/* for iso_map command */ 6436392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 6536392Ssklower 66*37469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 67*37469Ssklower extern u_long iso_hashchar(); 68*37469Ssklower static struct sockaddr_iso 69*37469Ssklower dst = {sizeof(dst), AF_ISO}, 70*37469Ssklower gte = {sizeof(dst), AF_ISO}, 71*37469Ssklower src = {sizeof(dst), AF_ISO}, 72*37469Ssklower msk = {sizeof(dst), AF_ISO}, 73*37469Ssklower zmk = {1}; 74*37469Ssklower #define zsi blank_siso 75*37469Ssklower #define zero_isoa zsi.siso_addr 76*37469Ssklower #define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \ 77*37469Ssklower ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len))) 78*37469Ssklower #define S(x) ((struct sockaddr *)&(x)) 79*37469Ssklower 8036392Ssklower #define SNPAC_HASH(addr) \ 81*37469Ssklower (((u_long) iso_hashchar((caddr_t)addr, (int)addr->isoa_len)) % SNPAC_NB) 8236392Ssklower 8336392Ssklower #define SNPAC_LOOK(sc,addr) { \ 8436392Ssklower register n; \ 8536392Ssklower sc = &iso_snpac[SNPAC_HASH(addr) * SNPAC_BSIZ]; \ 8636392Ssklower for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) \ 8736392Ssklower if ((sc->sc_flags & SNPA_VALID) && \ 8836392Ssklower (iso_addrmatch1(&sc->sc_nsap, addr))) \ 8936392Ssklower break; \ 9036392Ssklower if (n >= SNPAC_BSIZ) \ 9136392Ssklower sc = 0; \ 9236392Ssklower } 9336392Ssklower 9436392Ssklower struct snpa_cache *snpac_new(); 9536392Ssklower 9636392Ssklower /* 9736392Ssklower * We only keep track of a single IS at a time. 9836392Ssklower */ 9936392Ssklower struct snpa_cache *known_is; 10036392Ssklower 10136392Ssklower /* 10236392Ssklower * Addresses taken from NBS agreements, December 1987. 10336392Ssklower * 10436392Ssklower * These addresses assume on-the-wire transmission of least significant 10536392Ssklower * bit first. This is the method used by 802.3. When these 10636392Ssklower * addresses are passed to the token ring driver, (802.5), they 10736392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 10836392Ssklower * 10936392Ssklower * Furthermore, according to IBM Austin, these addresses are not 11036392Ssklower * true token ring multicast addresses. More work is necessary 11136392Ssklower * to get multicast to work right on token ring. 11236392Ssklower * 11336392Ssklower * Currently, the token ring driver does not handle multicast, so 11436392Ssklower * these addresses are converted into the broadcast address in 11536392Ssklower * lan_output() That means that if these multicast addresses change 11636392Ssklower * the token ring driver must be altered. 11736392Ssklower */ 11836392Ssklower struct snpa_cache all_es = { 11936392Ssklower { { 0x0 }, /* sc_nsap */ 12036392Ssklower 6, /* sc_len */ 12136392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }, /* sc_snpa */ 12236392Ssklower SNPA_VALID, /* sc_flags */ 12336392Ssklower 0 } /* sc_ht */ 12436392Ssklower }; 12536392Ssklower struct snpa_cache all_is = { 12636392Ssklower { { 0x0 }, /* sc_nsap */ 12736392Ssklower 6, /* sc_len */ 12836392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }, /* sc_snpa */ 12936392Ssklower SNPA_VALID, /* sc_flags */ 13036392Ssklower 0 } /* sc_ht */ 13136392Ssklower }; 13236392Ssklower 13336392Ssklower 13436392Ssklower /* 13536392Ssklower * FUNCTION: iso_snparesolve 13636392Ssklower * 13736392Ssklower * PURPOSE: Resolve an iso address into snpa address 13836392Ssklower * 13936392Ssklower * RETURNS: 0 if addr is resolved 14036392Ssklower * errno if addr is unknown 14136392Ssklower * 14236392Ssklower * SIDE EFFECTS: 14336392Ssklower * 14436392Ssklower * NOTES: If an entry is found that matches the address, that 14536392Ssklower * snpa is returned. If no entry is found, but an IS is 14636392Ssklower * known, then the address of the IS is returned. If 14736392Ssklower * neither an address is found that matches or an IS is 14836392Ssklower * known, then the multi-cast address for "all ES" for 14936392Ssklower * this interface is returned. 15036392Ssklower * 15136392Ssklower * NB: the last case described above constitutes the 15236392Ssklower * query configuration function 9542, sec 6.5 15336392Ssklower * A mechanism is needed to prevent this function from 15436392Ssklower * being invoked if the system is an IS. 15536392Ssklower */ 156*37469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 15736392Ssklower struct ifnet *ifp; /* outgoing interface */ 158*37469Ssklower struct sockaddr_iso *dest; /* destination */ 15936392Ssklower char *snpa; /* RESULT: snpa to be used */ 16036392Ssklower int *snpa_len; /* RESULT: length of snpa */ 16136392Ssklower { 16236392Ssklower extern struct ifnet loif; /* loopback interface */ 16336392Ssklower struct snpa_cache *sc; /* ptr to snpa table entry */ 16436392Ssklower struct iso_addr *destiso; /* destination iso addr */ 16536392Ssklower 166*37469Ssklower destiso = &dest->siso_addr; 16736392Ssklower 16836392Ssklower /* 16936392Ssklower * This hack allows us to send esis packets that have the destination snpa 17036392Ssklower * addresss embedded in the destination nsap address 17136392Ssklower */ 172*37469Ssklower if (destiso->isoa_genaddr[0] == AFI_SNA) { 17336392Ssklower /* 17436392Ssklower * This is a subnetwork address. Return it immediately 17536392Ssklower */ 17636392Ssklower IFDEBUG(D_SNPA) 17736392Ssklower printf("iso_snparesolve: return SN address\n"); 17836392Ssklower ENDDEBUG 17936392Ssklower 18036392Ssklower *snpa_len = destiso->isoa_len - 1; /* subtract size of AFI */ 181*37469Ssklower bcopy((caddr_t) destiso->isoa_genaddr + 1, (caddr_t)snpa, 182*37469Ssklower (unsigned)*snpa_len); 18336392Ssklower return (0); 18436392Ssklower } 18536392Ssklower 18636392Ssklower IFDEBUG(D_SNPA) 18736392Ssklower printf("iso_snparesolve: resolving %s\n", clnp_iso_addrp(destiso)); 18836392Ssklower ENDDEBUG 18936392Ssklower 19036392Ssklower /* 19136392Ssklower * packet is not for us, check cache for an entry 19236392Ssklower */ 19336392Ssklower SNPAC_LOOK(sc, destiso); 19436392Ssklower if (sc == 0) { /* not found */ 19536392Ssklower /* If we are an IS, we can't do much with the packet */ 19636392Ssklower if (iso_systype == SNPA_IS) 19736392Ssklower goto bad; 19836392Ssklower 19936392Ssklower /* 20036392Ssklower * Check if we know about an IS 20136392Ssklower */ 20236392Ssklower if ((known_is) && (known_is->sc_flags & SNPA_VALID)) { 20336392Ssklower sc = known_is; 20436392Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 20536392Ssklower /* 20636392Ssklower * no IS, no match. Return "all es" multicast address for this 20736392Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 20836392Ssklower * 20936392Ssklower * Note: there is a potential problem here. If the destination 21036392Ssklower * is on the subnet and it does not respond with a ESH, but 21136392Ssklower * does send back a TP CC, a connection could be established 21236392Ssklower * where we always transmit the CLNP packet to "all es" 21336392Ssklower */ 21436392Ssklower sc = &all_es; 21536392Ssklower } else { 21636392Ssklower goto bad; 21736392Ssklower } 21836392Ssklower } 21936392Ssklower 22036392Ssklower bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 22136392Ssklower *snpa_len = sc->sc_len; 22236392Ssklower return (0); 22336392Ssklower 22436392Ssklower bad: 22536392Ssklower return(ENETUNREACH); 22636392Ssklower } 22736392Ssklower 22836392Ssklower 22936392Ssklower /* 23036392Ssklower * FUNCTION: snpac_look 23136392Ssklower * 23236392Ssklower * PURPOSE: Look up an entry in the snpa cache 23336392Ssklower * 23436392Ssklower * RETURNS: Pointer to snpa_cache structure, or null 23536392Ssklower * 23636392Ssklower * SIDE EFFECTS: 23736392Ssklower * 23836392Ssklower * NOTES: This is simply SNPAC_LOOK as a procedure. 23936392Ssklower */ 24036392Ssklower struct snpa_cache * 24136392Ssklower snpac_look(isoa) 24236392Ssklower struct iso_addr *isoa; /* destination nsap */ 24336392Ssklower { 24436392Ssklower struct snpa_cache *sc; 24536392Ssklower int s = splimp(); 24636392Ssklower 24736392Ssklower SNPAC_LOOK(sc, isoa); 24836392Ssklower 24936392Ssklower splx(s); 25036392Ssklower return(sc); 25136392Ssklower } 25236392Ssklower 25336392Ssklower /* 25436392Ssklower * FUNCTION: iso_8208snparesolve 25536392Ssklower * 25636392Ssklower * PURPOSE: Find the X.121 address that corresponds to an NSAP addr 25736392Ssklower * 25836392Ssklower * RETURNS: 0 or unix errno 25936392Ssklower * 26036392Ssklower * SIDE EFFECTS: 26136392Ssklower * 26236392Ssklower * NOTES: This ought to invoke the 8208 ES-IS function 26336392Ssklower */ 264*37469Ssklower iso_8208snparesolve(dest, snpa, snpa_len) 265*37469Ssklower struct sockaddr_iso *dest; /* destination */ 26636392Ssklower char *snpa; /* RESULT: snpa to be used */ 26736392Ssklower int *snpa_len; /* RESULT: length of snpa */ 26836392Ssklower { 26936392Ssklower struct snpa_cache *sc; /* ptr to snpa table entry */ 27036392Ssklower struct iso_addr *destiso; /* destination iso addr */ 27136392Ssklower int s; 27236392Ssklower int err = 0; 27336392Ssklower 274*37469Ssklower destiso = &dest->siso_addr; 27536392Ssklower 27636392Ssklower s = splimp(); 27736392Ssklower SNPAC_LOOK(sc, destiso); 27836392Ssklower if (sc) { 27936392Ssklower bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 28036392Ssklower *snpa_len = sc->sc_len; 28136392Ssklower } else { 28236392Ssklower err = ENETUNREACH; 28336392Ssklower } 28436392Ssklower splx(s); 28536392Ssklower return (err); 28636392Ssklower } 28736392Ssklower 28836392Ssklower /* 28936392Ssklower * FUNCTION: iso_8208snpaadd 29036392Ssklower * 29136392Ssklower * PURPOSE: Add an entry to the snpa cache 29236392Ssklower * 29336392Ssklower * RETURNS: 29436392Ssklower * 29536392Ssklower * SIDE EFFECTS: 29636392Ssklower * 29736392Ssklower * NOTES: used by cons 29836392Ssklower */ 29936392Ssklower iso_8208snpaadd(ifp, nsap, snpa, snpalen, ht) 30036392Ssklower struct ifnet *ifp; /* interface info is related to */ 30136392Ssklower struct iso_addr *nsap; /* nsap to add */ 30236392Ssklower caddr_t snpa; /* translation */ 30336392Ssklower int snpalen; /* length in bytes */ 30436392Ssklower short ht; /* holding time (in seconds) */ 30536392Ssklower { 306*37469Ssklower snpac_add(ifp, nsap, snpa, snpalen, SNPA_ES, (u_short)ht); 30736392Ssklower } 30836392Ssklower 30936392Ssklower /* 31036392Ssklower * FUNCTION: iso_8208snpadelete 31136392Ssklower * 31236392Ssklower * PURPOSE: Delete an entry from the snpa cache 31336392Ssklower * 31436392Ssklower * RETURNS: nothing 31536392Ssklower * 31636392Ssklower * SIDE EFFECTS: 31736392Ssklower * 31836392Ssklower * NOTES: used by CONS 31936392Ssklower */ 32036392Ssklower iso_8208snpadelete(nsap) 32136392Ssklower struct iso_addr *nsap; 32236392Ssklower { 32336392Ssklower struct snpa_cache *sc = snpac_look(nsap); 32436392Ssklower 32536392Ssklower if (sc != NULL) 32636392Ssklower snpac_free(sc); 32736392Ssklower } 32836392Ssklower 32936392Ssklower /* 33036392Ssklower * FUNCTION: snpac_new 33136392Ssklower * 33236392Ssklower * PURPOSE: create a new entry in the iso address to ethernet 33336392Ssklower * address table 33436392Ssklower * 33536392Ssklower * RETURNS: pointer to newest entry 33636392Ssklower * 33736392Ssklower * SIDE EFFECTS: times out old entries if no new entries are found 33836392Ssklower * 33936392Ssklower * NOTES: If the bucket is full, then timeout the oldest entry 34036392Ssklower * (ie. the one with the youngest holding time) 34136392Ssklower */ 34236392Ssklower struct snpa_cache * 34336392Ssklower snpac_new(isoa) 34436392Ssklower struct iso_addr *isoa; /* iso address to enter into table */ 34536392Ssklower { 34636392Ssklower register struct snpa_cache *sc; 34736392Ssklower register int n; 34836392Ssklower int smallest_ht = 1000000; 34936392Ssklower struct snpa_cache *maybe; 35036392Ssklower 35136392Ssklower sc = &iso_snpac[SNPAC_HASH(isoa) * SNPAC_BSIZ]; 35236392Ssklower for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) { 35336392Ssklower 35436392Ssklower IFDEBUG (D_IOCTL) 35536392Ssklower printf("snpac_new: sc x%x ", sc); 35636392Ssklower 35736392Ssklower if (sc->sc_flags & SNPA_VALID) { 35836392Ssklower int i; 35936392Ssklower 36036392Ssklower printf("(valid) %s ", clnp_iso_addrp(&sc->sc_nsap)); 36136392Ssklower for (i=0; i<sc->sc_len; i++) 36236392Ssklower printf("%x%c", sc->sc_snpa[i], i < (sc->sc_len-1) ? ':' 36336392Ssklower : '\n'); 36436392Ssklower } else { 36536392Ssklower printf("invalid\n"); 36636392Ssklower } 36736392Ssklower ENDDEBUG 36836392Ssklower 36936392Ssklower if (sc->sc_flags & SNPA_VALID) { 37036392Ssklower if (sc->sc_ht < smallest_ht) { 37136392Ssklower smallest_ht = sc->sc_ht; 37236392Ssklower maybe = sc; 37336392Ssklower } 37436392Ssklower } else { 37536392Ssklower return sc; /* found unused slot */ 37636392Ssklower } 37736392Ssklower } 37836392Ssklower snpac_free(maybe); 37936392Ssklower return maybe; 38036392Ssklower } 38136392Ssklower /* 38236392Ssklower * FUNCTION: snpac_free 38336392Ssklower * 38436392Ssklower * PURPOSE: free an entry in the iso address map table 38536392Ssklower * 38636392Ssklower * RETURNS: nothing 38736392Ssklower * 38836392Ssklower * SIDE EFFECTS: 38936392Ssklower * 39036392Ssklower * NOTES: If there is a route entry associated with cache 39136392Ssklower * entry, then delete that as well 39236392Ssklower */ 39336392Ssklower snpac_free(sc) 39436392Ssklower register struct snpa_cache *sc; /* entry to free */ 39536392Ssklower { 396*37469Ssklower register struct rtentry *rt; 397*37469Ssklower register struct iso_addr *r; 39836392Ssklower 39936392Ssklower if (known_is == sc) { 40036392Ssklower known_is = NULL; 40136392Ssklower } 402*37469Ssklower if (sc->sc_rt) { 403*37469Ssklower zap_isoaddr(dst, (&(sc->sc_da))); 404*37469Ssklower rt = rtalloc1((struct sockaddr *)&dst, 0); 405*37469Ssklower if ((sc->sc_rt == rt) && (rt->rt_flags & RTF_UP) 406*37469Ssklower && (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 407*37469Ssklower RTFREE(rt); 408*37469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 409*37469Ssklower rt->rt_flags, (struct rtentry **)0); 410*37469Ssklower } 411*37469Ssklower RTFREE(rt); 41236392Ssklower } 41336392Ssklower bzero((caddr_t)sc, sizeof(struct snpa_cache)); 41436392Ssklower } 41536392Ssklower 41636392Ssklower /* 41736392Ssklower * FUNCTION: snpac_add 41836392Ssklower * 41936392Ssklower * PURPOSE: Add an entry to the snpa cache 42036392Ssklower * 42136392Ssklower * RETURNS: 42236392Ssklower * 42336392Ssklower * SIDE EFFECTS: 42436392Ssklower * 42536392Ssklower * NOTES: If entry already exists, then update holding time. 42636392Ssklower */ 42736392Ssklower snpac_add(ifp, nsap, snpa, snpalen, type, ht) 42836392Ssklower struct ifnet *ifp; /* interface info is related to */ 42936392Ssklower struct iso_addr *nsap; /* nsap to add */ 43036392Ssklower caddr_t snpa; /* translation */ 431*37469Ssklower int snpalen; /* translation length */ 43236392Ssklower char type; /* SNPA_IS or SNPA_ES */ 433*37469Ssklower u_short ht; /* holding time (in seconds) */ 43436392Ssklower { 43536392Ssklower struct snpa_cache *sc; 43636392Ssklower 43736392Ssklower SNPAC_LOOK(sc, nsap); 43836392Ssklower if (sc == NULL) { 43936392Ssklower sc = snpac_new(nsap); 44036392Ssklower sc->sc_nsap = *nsap; 44136392Ssklower } 44236392Ssklower 44336392Ssklower sc->sc_ht = ht; 44436392Ssklower 44536392Ssklower sc->sc_len = min(snpalen, MAX_SNPALEN); 446*37469Ssklower bcopy(snpa, (caddr_t)sc->sc_snpa, sc->sc_len); 44736392Ssklower sc->sc_flags = SNPA_VALID | type; 44836392Ssklower sc->sc_ifp = ifp; 44936392Ssklower 45036392Ssklower if (type & SNPA_IS) 45136392Ssklower snpac_logdefis(sc); 45236392Ssklower } 45336392Ssklower 45436392Ssklower /* 45536392Ssklower * FUNCTION: snpac_ioctl 45636392Ssklower * 45736392Ssklower * PURPOSE: handle ioctls to change the iso address map 45836392Ssklower * 45936392Ssklower * RETURNS: unix error code 46036392Ssklower * 46136392Ssklower * SIDE EFFECTS: changes the snpa_cache table declared above. 46236392Ssklower * 46336392Ssklower * NOTES: 46436392Ssklower */ 46536392Ssklower snpac_ioctl(cmd, data) 46636392Ssklower int cmd; /* ioctl to process */ 46736392Ssklower caddr_t data; /* data for the cmd */ 46836392Ssklower { 46936392Ssklower register struct snpa_req *rq = (struct snpa_req *)data; 47036392Ssklower register struct snpa_cache *sc; 47136392Ssklower register struct iso_addr *isoa; 47236392Ssklower int s; 473*37469Ssklower char *type; 47436392Ssklower 475*37469Ssklower switch(cmd) { 476*37469Ssklower case SIOCSISOMAP: type = "set"; break; 477*37469Ssklower case SIOCDISOMAP: type = "delete"; break; 478*37469Ssklower case SIOCGISOMAP: type = "get"; break; 479*37469Ssklower default: return(snpac_systype(cmd, data)); 480*37469Ssklower } 48136392Ssklower 48236392Ssklower /* sanity check */ 48336392Ssklower if (rq->sr_len > MAX_SNPALEN) 48436392Ssklower return(EINVAL); 48536392Ssklower 48636392Ssklower IFDEBUG (D_IOCTL) 48736392Ssklower int i; 48836392Ssklower 489*37469Ssklower printf("snpac_ioctl: %s %s to ", type, clnp_iso_addrp(isoa)); 49036392Ssklower for (i=0; i<rq->sr_len; i++) 49136392Ssklower printf("%x%c", rq->sr_snpa[i], i < (rq->sr_len-1) ? ':' : '\n'); 49236392Ssklower ENDDEBUG 49336392Ssklower 494*37469Ssklower /* look up this address in table */ 495*37469Ssklower isoa = &rq->sr_isoa; 496*37469Ssklower 49736392Ssklower SNPAC_LOOK(sc, isoa); 49836392Ssklower if (sc == NULL) { /* not found */ 49936392Ssklower if (cmd != SIOCSISOMAP) 50036392Ssklower return(ENXIO); 50136392Ssklower } 50236392Ssklower 50336392Ssklower switch(cmd) { 50436392Ssklower case SIOCSISOMAP: /* set entry */ 505*37469Ssklower snpac_add((struct ifnet *)NULL, isoa, (caddr_t)rq->sr_snpa, 506*37469Ssklower (int)rq->sr_len, 507*37469Ssklower (char)(rq->sr_flags & (SNPA_ES|SNPA_IS|SNPA_PERM)), 508*37469Ssklower rq->sr_ht); 50936392Ssklower break; 51036392Ssklower 51136392Ssklower case SIOCDISOMAP: /* delete entry */ 51236392Ssklower snpac_free(sc); 51336392Ssklower break; 51436392Ssklower 51536392Ssklower case SIOCGISOMAP: /* get entry */ 516*37469Ssklower bcopy((caddr_t)&sc->sc_sr, (caddr_t)rq, sizeof(struct snpa_req)); 51736392Ssklower break; 51836392Ssklower } 51936392Ssklower return(0); 52036392Ssklower } 52136392Ssklower 52236392Ssklower /* 52336392Ssklower * FUNCTION: iso_tryloopback 52436392Ssklower * 52536392Ssklower * PURPOSE: Attempt to use the software loopback interface for pkt 52636392Ssklower * 52736392Ssklower * RETURNS: 0 if packet was sent successfully 52836392Ssklower * errno if there was a problem sending the packet 52936392Ssklower * Ie. the return value of looutput 53036392Ssklower * -1 if software loopback is not appropriate 53136392Ssklower * 53236392Ssklower * SIDE EFFECTS: 53336392Ssklower * 53436392Ssklower * NOTES: 53536392Ssklower */ 536*37469Ssklower iso_tryloopback(m, dest) 53736392Ssklower struct mbuf *m; /* pkt */ 538*37469Ssklower struct sockaddr_iso *dest; /* destination */ 53936392Ssklower { 54036392Ssklower struct iso_addr *destiso; /* destination iso addr */ 54136392Ssklower 542*37469Ssklower destiso = &dest->siso_addr; 54336392Ssklower 54436392Ssklower if (clnp_ours(destiso)) { 54536392Ssklower IFDEBUG(D_SNPA) 54636392Ssklower printf("iso_tryloopback: local destination\n"); 54736392Ssklower ENDDEBUG 54836392Ssklower if (loif.if_flags & IFF_UP) { 54936392Ssklower IFDEBUG(D_SNPA) 55036392Ssklower printf("iso_tryloopback: calling looutput\n"); 55136392Ssklower ENDDEBUG 552*37469Ssklower return (looutput(&loif, m, (struct sockaddr *)dest)); 55336392Ssklower } 55436392Ssklower } 55536392Ssklower return (-1); 55636392Ssklower } 55736392Ssklower 55836392Ssklower /* 55936392Ssklower * FUNCTION: snpac_systype 56036392Ssklower * 56136392Ssklower * PURPOSE: Set/Get the system type and esis parameters 56236392Ssklower * 56336392Ssklower * RETURNS: 0 on success, or unix error code 56436392Ssklower * 56536392Ssklower * SIDE EFFECTS: 56636392Ssklower * 56736392Ssklower * NOTES: 56836392Ssklower */ 56936392Ssklower snpac_systype (cmd, data) 57036392Ssklower int cmd; /* ioctl to process */ 57136392Ssklower caddr_t data; /* data for the cmd */ 57236392Ssklower { 57336392Ssklower register struct systype_req *rq = (struct systype_req *)data; 57436392Ssklower extern short esis_holding_time, esis_config_time; 57536392Ssklower 57636392Ssklower IFDEBUG (D_IOCTL) 57736392Ssklower if (cmd == SIOCSSTYPE) 57836392Ssklower printf("snpac_systype: cmd set, type x%x, ht %d, ct %d\n", 57936392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 58036392Ssklower else 58136392Ssklower printf("snpac_systype: cmd get\n"); 58236392Ssklower ENDDEBUG 58336392Ssklower 58436392Ssklower if (cmd == SIOCSSTYPE) { 58536392Ssklower if (!suser()) 58636392Ssklower return(EACCES); 58736392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 58836392Ssklower return(EINVAL); 58936392Ssklower if (rq->sr_type & SNPA_ES) { 59036392Ssklower iso_systype = SNPA_ES; 59136392Ssklower } else if (rq->sr_type & SNPA_IS) { 59236392Ssklower iso_systype = SNPA_IS; 59336392Ssklower } else { 59436392Ssklower return(EINVAL); 59536392Ssklower } 59636392Ssklower esis_holding_time = rq->sr_holdt; 59736392Ssklower esis_config_time = rq->sr_configt; 59836392Ssklower } else if (cmd == SIOCGSTYPE) { 59936392Ssklower rq->sr_type = iso_systype; 60036392Ssklower rq->sr_holdt = esis_holding_time; 60136392Ssklower rq->sr_configt = esis_config_time; 60236392Ssklower } else { 60336392Ssklower return(EINVAL); 60436392Ssklower } 60536392Ssklower return(0); 60636392Ssklower } 60736392Ssklower 60836392Ssklower /* 60936392Ssklower * FUNCTION: snpac_logdefis 61036392Ssklower * 61136392Ssklower * PURPOSE: Mark the IS passed as the default IS 61236392Ssklower * 61336392Ssklower * RETURNS: nothing 61436392Ssklower * 61536392Ssklower * SIDE EFFECTS: 61636392Ssklower * 61736392Ssklower * NOTES: 61836392Ssklower */ 61936392Ssklower snpac_logdefis(sc) 620*37469Ssklower register struct snpa_cache *sc; 62136392Ssklower { 622*37469Ssklower register struct iso_addr *r; 623*37469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 624*37469Ssklower if (known_is == 0) 625*37469Ssklower known_is = sc; 626*37469Ssklower if (known_is != sc) { 627*37469Ssklower if (known_is->sc_rt) { 628*37469Ssklower rtfree(known_is->sc_rt); 629*37469Ssklower known_is->sc_rt = 0; 630*37469Ssklower } 631*37469Ssklower known_is = sc; 63236392Ssklower } 633*37469Ssklower if (rt == 0) { 634*37469Ssklower zap_isoaddr(dst, &(sc->sc_nsap)); 635*37469Ssklower rtrequest(RTM_ADD, S(zsi), S(dst), S(zmk), 636*37469Ssklower RTF_DYNAMIC|RTF_GATEWAY, &sc->sc_rt); 637*37469Ssklower return; 638*37469Ssklower } 639*37469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 640*37469Ssklower ((struct sockaddr_iso *)rt->rt_gateway)->siso_addr = sc->sc_nsap; 641*37469Ssklower known_is = sc; 642*37469Ssklower sc->sc_rt = rt; 643*37469Ssklower } 64436392Ssklower } 64536392Ssklower 64636392Ssklower /* 64736392Ssklower * FUNCTION: snpac_age 64836392Ssklower * 64936392Ssklower * PURPOSE: Time out snpac entries 65036392Ssklower * 65136392Ssklower * RETURNS: 65236392Ssklower * 65336392Ssklower * SIDE EFFECTS: 65436392Ssklower * 65536392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 65636392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 65736392Ssklower * if the entry is added a moment before snpac_age is 65836392Ssklower * called, the entry will immediately have SNPAC_AGE 65936392Ssklower * seconds taken off the holding time, even though 66036392Ssklower * it has only been held a brief moment. 66136392Ssklower * 66236392Ssklower * The proper way to do this is set an expiry timeval 66336392Ssklower * equal to current time + holding time. Then snpac_age 66436392Ssklower * would time out entries where expiry date is older 66536392Ssklower * than the current time. 66636392Ssklower */ 66736392Ssklower snpac_age() 66836392Ssklower { 66936392Ssklower register struct snpa_cache *sc; 67036392Ssklower register int i; 67136392Ssklower 67236392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 67336392Ssklower 67436392Ssklower sc = &iso_snpac[0]; 67536392Ssklower for (i=0; i<SNPAC_SIZE; i++, sc++) { 67636392Ssklower if (((sc->sc_flags & SNPA_PERM) == 0) && (sc->sc_flags & SNPA_VALID)) { 67736392Ssklower sc->sc_ht -= SNPAC_AGE; 67836392Ssklower if (sc->sc_ht > 0) 67936392Ssklower continue; 68036392Ssklower else 68136392Ssklower snpac_free(sc); 68236392Ssklower } 68336392Ssklower } 68436392Ssklower } 68536392Ssklower 68636392Ssklower /* 68736392Ssklower * FUNCTION: snpac_ownmulti 68836392Ssklower * 68936392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 69036392Ssklower * of the same type as the system. 69136392Ssklower * 69236392Ssklower * RETURNS: true or false 69336392Ssklower * 69436392Ssklower * SIDE EFFECTS: 69536392Ssklower * 69636392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 69736392Ssklower * as interm kludge until 69836392Ssklower * real multicast addresses can be configured 69936392Ssklower */ 70036392Ssklower snpac_ownmulti(snpa, len) 70136392Ssklower char *snpa; 70236392Ssklower int len; 70336392Ssklower { 704*37469Ssklower return (((iso_systype & SNPA_ES) && 705*37469Ssklower (!bcmp((caddr_t)snpa, (caddr_t)all_es.sc_snpa, (unsigned)len))) || 706*37469Ssklower ((iso_systype & SNPA_IS) && 707*37469Ssklower (!bcmp((caddr_t)snpa, (caddr_t)all_is.sc_snpa, (unsigned)len)))); 70836392Ssklower } 70936392Ssklower 71036392Ssklower /* 71136392Ssklower * FUNCTION: snpac_flushifp 71236392Ssklower * 71336392Ssklower * PURPOSE: Flush entries associated with specific ifp 71436392Ssklower * 71536392Ssklower * RETURNS: nothing 71636392Ssklower * 71736392Ssklower * SIDE EFFECTS: 71836392Ssklower * 71936392Ssklower * NOTES: 72036392Ssklower */ 72136392Ssklower snpac_flushifp(ifp) 72236392Ssklower struct ifnet *ifp; 72336392Ssklower { 72436392Ssklower register struct snpa_cache *sc; 72536392Ssklower register int i; 72636392Ssklower 72736392Ssklower sc = &iso_snpac[0]; 72836392Ssklower for (i=0; i<SNPAC_SIZE; i++, sc++) { 72936392Ssklower if ((sc->sc_ifp == ifp) && (sc->sc_flags & SNPA_VALID)) { 73036392Ssklower snpac_free(sc); 73136392Ssklower } 73236392Ssklower } 73336392Ssklower } 73436392Ssklower 73536392Ssklower /* 73636392Ssklower * FUNCTION: snpac_rtrequest 73736392Ssklower * 73836392Ssklower * PURPOSE: Make a routing request 73936392Ssklower * 74036392Ssklower * RETURNS: nothing 74136392Ssklower * 74236392Ssklower * SIDE EFFECTS: 74336392Ssklower * 74436392Ssklower * NOTES: In the future, this should make a request of a user 74536392Ssklower * level routing daemon. 74636392Ssklower */ 747*37469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 74836392Ssklower int req; 749*37469Ssklower struct iso_addr *host; 75036392Ssklower struct iso_addr *gateway; 751*37469Ssklower struct iso_addr *netmask; 75236392Ssklower short flags; 753*37469Ssklower struct rtentry **ret_nrt; 75436392Ssklower { 755*37469Ssklower register struct iso_addr *r; 75636392Ssklower 75736392Ssklower IFDEBUG(D_SNPA) 75836392Ssklower printf("snpac_rtrequest: "); 759*37469Ssklower if (req == RTM_ADD) 76036392Ssklower printf("add"); 761*37469Ssklower else if (req == RTM_DELETE) 76236392Ssklower printf("delete"); 76336392Ssklower else 76436392Ssklower printf("unknown command"); 765*37469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 76636392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 76736392Ssklower ENDDEBUG 76836392Ssklower 76936392Ssklower 770*37469Ssklower zap_isoaddr(dst, host); 771*37469Ssklower zap_isoaddr(gte, gateway); 772*37469Ssklower zap_isoaddr(msk, netmask); 773*37469Ssklower 774*37469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 775*37469Ssklower flags, ret_nrt); 77636392Ssklower } 77736392Ssklower 77836392Ssklower /* 77936392Ssklower * FUNCTION: snpac_addrt 78036392Ssklower * 78136392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 78236392Ssklower * 78336392Ssklower * RETURNS: nothing 78436392Ssklower * 78536392Ssklower * SIDE EFFECTS: 78636392Ssklower * 78736392Ssklower * NOTES: If a cache entry exists for gateway, then 78836392Ssklower * make a routing entry (host, gateway) and associate 78936392Ssklower * with gateway. 79036392Ssklower * 79136392Ssklower * If a route already exists and is different, first delete 79236392Ssklower * it. 79336392Ssklower * 79436392Ssklower * This could be made more efficient by checking 79536392Ssklower * the existing route before adding a new one. 79636392Ssklower */ 797*37469Ssklower snpac_addrt(host, gateway, source, netmask) 798*37469Ssklower struct iso_addr *host, *gateway, *source, *netmask; 79936392Ssklower { 800*37469Ssklower register struct snpa_cache *sc; 801*37469Ssklower register struct iso_addr *r; 80236392Ssklower 80336392Ssklower SNPAC_LOOK(sc, gateway); 80436392Ssklower if (sc != NULL) { 805*37469Ssklower bcopy((caddr_t)host, (caddr_t)&sc->sc_da, sizeof(struct iso_addr)); 806*37469Ssklower zap_isoaddr(dst, host); 807*37469Ssklower zap_isoaddr(gte, gateway); 808*37469Ssklower zap_isoaddr(src, source); 809*37469Ssklower zap_isoaddr(msk, netmask); 810*37469Ssklower if (netmask) { 811*37469Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(src), &sc->sc_rt); 812*37469Ssklower } else 813*37469Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 814*37469Ssklower RTF_DONE | RTF_HOST, S(src), &sc->sc_rt); 81536392Ssklower } 81636392Ssklower } 81736392Ssklower #endif ISO 818