136367Ssklower /*********************************************************** 236367Ssklower Copyright IBM Corporation 1987 336367Ssklower 436367Ssklower All Rights Reserved 536367Ssklower 636367Ssklower Permission to use, copy, modify, and distribute this software and its 736367Ssklower documentation for any purpose and without fee is hereby granted, 836367Ssklower provided that the above copyright notice appear in all copies and that 936367Ssklower both that copyright notice and this permission notice appear in 1036367Ssklower supporting documentation, and that the name of IBM not be 1136367Ssklower used in advertising or publicity pertaining to distribution of the 1236367Ssklower software without specific, written prior permission. 1336367Ssklower 1436367Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536367Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636367Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736367Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836367Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936367Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036367Ssklower SOFTWARE. 2136367Ssklower 2236367Ssklower ******************************************************************/ 2336367Ssklower 2436367Ssklower /* 2536367Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636367Ssklower */ 2736367Ssklower /* $Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $ */ 2836367Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_arp.c,v $ */ 2936367Ssklower 3036367Ssklower #ifndef lint 3136367Ssklower static char *rcsid = "$Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $"; 3236367Ssklower #endif lint 3336367Ssklower 3436367Ssklower #ifdef ISO 3536367Ssklower 3636367Ssklower #include "../h/types.h" 3736367Ssklower #include "../h/param.h" 3836367Ssklower #include "../h/mbuf.h" 3936367Ssklower #include "../h/domain.h" 4036367Ssklower #include "../h/protosw.h" 4136367Ssklower #include "../h/socket.h" 4236367Ssklower #include "../h/socketvar.h" 4336367Ssklower #include "../h/errno.h" 4436367Ssklower #include "../h/ioctl.h" 4536367Ssklower 4636367Ssklower #include "../net/if.h" 4736367Ssklower #include "../net/route.h" 4836367Ssklower 49*37470Ssklower #include "iso.h" 50*37470Ssklower #include "iso_var.h" 51*37470Ssklower #include "iso_map.h" 52*37470Ssklower #include "iso_snpac.h" 53*37470Ssklower #include "clnp.h" 54*37470Ssklower #include "clnp_stat.h" 55*37470Ssklower #include "argo_debug.h" 5636367Ssklower 5736367Ssklower #define MAPTAB_BSIZ 20 /* bucket size */ 5836367Ssklower #define MAPTAB_NB 13 /* number of buckets */ 5936367Ssklower #define MAPTAB_SIZE (MAPTAB_BSIZ * MAPTAB_NB) 6036367Ssklower struct maptab iso_maptab[MAPTAB_SIZE]; 6136367Ssklower int iso_maptab_size = MAPTAB_SIZE; /* for isomap command */ 6236367Ssklower 6336367Ssklower #define MAPTAB_HASH(addr) \ 6436367Ssklower (((u_long) iso_hashchar(addr, addr->isoa_len)) % MAPTAB_NB) 6536367Ssklower 6636367Ssklower #define MAPTAB_LOOK(at,addr) { \ 6736367Ssklower register n; \ 6836367Ssklower at = &iso_maptab[MAPTAB_HASH(addr) * MAPTAB_BSIZ]; \ 6936367Ssklower for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) \ 7036367Ssklower if ((at->map_valid) && (iso_addrmatch1(&at->map_isoa, addr))) \ 7136367Ssklower break; \ 7236367Ssklower if (n >= MAPTAB_BSIZ) \ 7336367Ssklower at = 0; \ 7436367Ssklower } 7536367Ssklower 7636367Ssklower /* 7736367Ssklower * FUNCTION: clnp_arpresolve 7836367Ssklower * 7936367Ssklower * PURPOSE: Resolve a clnp address into hardware ethernet addr. 8036367Ssklower * 8136367Ssklower * RETURNS: 1 if addr is resolved 8236367Ssklower * 0 if addr is unknown 8336367Ssklower * 8436367Ssklower * SIDE EFFECTS: 8536367Ssklower * 8636367Ssklower * NOTES: This is a hack. If the address is local, then 8736367Ssklower * the packet is put on the loopback driver. Otherwise, 8836367Ssklower * if a translation is found, that ethernet address is 8936367Ssklower * returned. Otherwise, the packet is dropped. Thus, 9036367Ssklower * each translation must be placed (by hand) in the 9136367Ssklower * tables (see isomap(8)). 9236367Ssklower * TODO: should this map stuff be a critical section? 9336367Ssklower */ 9436367Ssklower clnp_arpresolve(ifp, m, dst, edst) 9536367Ssklower struct ifnet *ifp; /* outgoing interface */ 9636367Ssklower struct mbuf *m; /* pkt */ 9736367Ssklower struct sockaddr_iso *dst; /* destination */ 9836367Ssklower char *edst; /* RESULT: ethernet address */ 9936367Ssklower { 10036367Ssklower extern struct ifnet loif; /* loopback interface */ 10136367Ssklower struct maptab *at; /* ptr to map table entry */ 10236367Ssklower struct iso_addr *destiso; /* destination iso addr */ 10336367Ssklower 10436367Ssklower destiso = &dst->siso_addr; 10536367Ssklower 106*37470Ssklower if (destiso->isoa_genaddr[0] == AFI_SNA) { 10736367Ssklower /* 10836367Ssklower * This is a subnetwork address. Return it immediately 10936367Ssklower */ 11036367Ssklower int sna_len; 11136367Ssklower 11236367Ssklower IFDEBUG(D_ESISOUTPUT) 11336367Ssklower printf("clnp_arpresolve: return SN address\n"); 11436367Ssklower ENDDEBUG 11536367Ssklower 11636367Ssklower sna_len = destiso->isoa_len - 1; /* subtract size of AFI */ 11736367Ssklower if (sna_len != 6) { 11836367Ssklower IFDEBUG(D_ESISOUTPUT) 11936367Ssklower printf("clnp_arpresolve: SN len is bad (%d)\n", sna_len); 12036367Ssklower ENDDEBUG 12136367Ssklower return(-1); 12236367Ssklower } 123*37470Ssklower bcopy((caddr_t)&destiso->isoa_genaddr[1], (caddr_t)edst, sna_len); 12436367Ssklower return (1); 12536367Ssklower } 12636367Ssklower 12736367Ssklower IFDEBUG(D_ETHER) 12836367Ssklower printf("clnp_arpresolve: resolving %s\n", clnp_iso_addrp(destiso)); 12936367Ssklower ENDDEBUG 13036367Ssklower 13136367Ssklower /* if for us, use software loopback driver if up */ 13236367Ssklower if (clnp_ours(destiso)) { 13336367Ssklower IFDEBUG(D_ETHER) 13436367Ssklower printf("clnp_arpresolve: local destination\n"); 13536367Ssklower ENDDEBUG 13636367Ssklower if (loif.if_flags & IFF_UP) { 13736367Ssklower IFDEBUG(D_ETHER) 13836367Ssklower printf("clnp_arpresolve: calling looutput\n"); 13936367Ssklower ENDDEBUG 14036367Ssklower (void) looutput(&loif, m, (struct sockaddr *)dst); 14136367Ssklower /* 14236367Ssklower * The packet has already been sent and freed. 14336367Ssklower */ 14436367Ssklower return (0); 14536367Ssklower } 14636367Ssklower } 14736367Ssklower 14836367Ssklower IFDEBUG(D_ETHER) 14936367Ssklower printf("clnp_arpresolve: NON-local destination\n"); 15036367Ssklower ENDDEBUG 15136367Ssklower 15236367Ssklower /* 15336367Ssklower * packet is not for us, check static map table for an entry 15436367Ssklower * This does not need to be a critical section because the 15536367Ssklower * table is not dynamically updated, except by a call to 15636367Ssklower * isomap(8) 15736367Ssklower */ 15836367Ssklower MAPTAB_LOOK(at, destiso); 15936367Ssklower if (at == 0) { /* not found */ 16036367Ssklower m_freem(m); 16136367Ssklower return (-1); 16236367Ssklower } else { 16336367Ssklower bcopy((caddr_t)at->map_enaddr, (caddr_t)edst, sizeof(at->map_enaddr)); 16436367Ssklower return (1); 16536367Ssklower } 16636367Ssklower } 16736367Ssklower 16836367Ssklower /* 16936367Ssklower * FUNCTION: isomap_new 17036367Ssklower * 17136367Ssklower * PURPOSE: create a new entry in the iso address to ethernet 17236367Ssklower * address table 17336367Ssklower * 17436367Ssklower * RETURNS: pointer to newest entry, or NULL if none can be found 17536367Ssklower * 17636367Ssklower * SIDE EFFECTS: 17736367Ssklower * 17836367Ssklower * NOTES: TODO: timeout old entries 17936367Ssklower */ 18036367Ssklower struct maptab * 18136367Ssklower isomap_new(isoa) 18236367Ssklower struct iso_addr *isoa; /* iso address to enter into table */ 18336367Ssklower { 18436367Ssklower register struct maptab *at; 18536367Ssklower register int n; 18636367Ssklower 18736367Ssklower at = &iso_maptab[MAPTAB_HASH(isoa) * MAPTAB_BSIZ]; 18836367Ssklower for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) { 18936367Ssklower 19036367Ssklower IFDEBUG (D_IOCTL) 19136367Ssklower printf("isomap_new: at x%x ", at); 19236367Ssklower 19336367Ssklower if (at->map_valid) { 19436367Ssklower int i; 19536367Ssklower 19636367Ssklower printf("(valid) %s ", clnp_iso_addrp(&at->map_isoa)); 19736367Ssklower for (i=0; i<6; i++) 19836367Ssklower printf("%x%c", at->map_enaddr[i], i < 5 ? ':' : '\n'); 19936367Ssklower } else { 20036367Ssklower printf("invalid\n"); 20136367Ssklower } 20236367Ssklower ENDDEBUG 20336367Ssklower 20436367Ssklower if (!at->map_valid) /* found unused slot */ 20536367Ssklower return at; 20636367Ssklower } 20736367Ssklower return NULL; 20836367Ssklower } 20936367Ssklower 21036367Ssklower /* 21136367Ssklower * FUNCTION: isomap_free 21236367Ssklower * 21336367Ssklower * PURPOSE: free an entry in the iso address map table 21436367Ssklower * 21536367Ssklower * RETURNS: nothing 21636367Ssklower * 21736367Ssklower * SIDE EFFECTS: 21836367Ssklower * 21936367Ssklower * NOTES: 22036367Ssklower */ 22136367Ssklower isomap_free(at) 22236367Ssklower register struct maptab *at; /* entry to free */ 22336367Ssklower { 22436367Ssklower at->map_valid = 0; 22536367Ssklower } 22636367Ssklower 22736367Ssklower /* 22836367Ssklower * FUNCTION: isomap_ioctl 22936367Ssklower * 23036367Ssklower * PURPOSE: handle ioctls to change the iso address map 23136367Ssklower * 23236367Ssklower * RETURNS: unix error code 23336367Ssklower * 23436367Ssklower * SIDE EFFECTS: changes the maptab table declared above. 23536367Ssklower * 23636367Ssklower * NOTES: 23736367Ssklower */ 23836367Ssklower isomap_ioctl(cmd, data) 23936367Ssklower int cmd; /* ioctl to process */ 24036367Ssklower caddr_t data; /* data for the cmd */ 24136367Ssklower { 242*37470Ssklower register struct arpreq_iso *ar = (struct arpreq_iso *)data; 24336367Ssklower register struct maptab *at; 24436367Ssklower register struct sockaddr_iso *siso; 24536367Ssklower register struct iso_addr *isoa; 24636367Ssklower 24736367Ssklower /* 24836367Ssklower * only process commands for the ISO address family 24936367Ssklower */ 250*37470Ssklower if (ar->arp_pa.siso_family != AF_ISO) 25136367Ssklower return(EAFNOSUPPORT); 25236367Ssklower 25336367Ssklower /* look up this address in table */ 25436367Ssklower siso = (struct sockaddr_iso *)&ar->arp_pa; 25536367Ssklower isoa = &siso->siso_addr; 25636367Ssklower 25736367Ssklower IFDEBUG (D_IOCTL) 25836367Ssklower int i; 25936367Ssklower 26036367Ssklower printf("isomap_ioctl: "); 26136367Ssklower switch(cmd) { 26236367Ssklower case SIOCSISOMAP: printf("set"); break; 26336367Ssklower case SIOCDISOMAP: printf("delete"); break; 26436367Ssklower case SIOCGISOMAP: printf("get"); break; 26536367Ssklower } 26636367Ssklower printf(" %s to ", clnp_iso_addrp(isoa)); 26736367Ssklower for (i=0; i<6; i++) 26836367Ssklower printf("%x%c", ar->arp_ha.sa_data[i], i < 5 ? ':' : '\n'); 26936367Ssklower ENDDEBUG 27036367Ssklower 27136367Ssklower MAPTAB_LOOK(at, isoa); 27236367Ssklower if (at == NULL) { /* not found */ 27336367Ssklower if (cmd != SIOCSISOMAP) 27436367Ssklower return(ENXIO); 27536367Ssklower 27636367Ssklower /* TODO: what if setting and net is not directly attached */ 27736367Ssklower } 27836367Ssklower 27936367Ssklower switch(cmd) { 28036367Ssklower case SIOCSISOMAP: /* set entry */ 28136367Ssklower if (at == NULL) { 28236367Ssklower at = isomap_new(isoa); 28336367Ssklower if (at == NULL) 28436367Ssklower return(ENOBUFS); 28536367Ssklower } 28636367Ssklower bcopy((caddr_t)isoa, (caddr_t)&at->map_isoa, 28736367Ssklower sizeof (struct iso_addr)); 28836367Ssklower bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->map_enaddr, 28936367Ssklower sizeof(at->map_enaddr)); 29036367Ssklower at->map_valid++; 29136367Ssklower break; 29236367Ssklower 29336367Ssklower case SIOCDISOMAP: /* delete entry */ 29436367Ssklower isomap_free(at); 29536367Ssklower break; 29636367Ssklower 29736367Ssklower case SIOCGISOMAP: /* get entry */ 29836367Ssklower bcopy((caddr_t)at->map_enaddr, (caddr_t)ar->arp_ha.sa_data, 29936367Ssklower sizeof(at->map_enaddr)); 30036367Ssklower } 30136367Ssklower return(0); 30236367Ssklower } 30336367Ssklower #endif ISO 304