1*36367Ssklower /*********************************************************** 2*36367Ssklower Copyright IBM Corporation 1987 3*36367Ssklower 4*36367Ssklower All Rights Reserved 5*36367Ssklower 6*36367Ssklower Permission to use, copy, modify, and distribute this software and its 7*36367Ssklower documentation for any purpose and without fee is hereby granted, 8*36367Ssklower provided that the above copyright notice appear in all copies and that 9*36367Ssklower both that copyright notice and this permission notice appear in 10*36367Ssklower supporting documentation, and that the name of IBM not be 11*36367Ssklower used in advertising or publicity pertaining to distribution of the 12*36367Ssklower software without specific, written prior permission. 13*36367Ssklower 14*36367Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36367Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36367Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36367Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36367Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36367Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36367Ssklower SOFTWARE. 21*36367Ssklower 22*36367Ssklower ******************************************************************/ 23*36367Ssklower 24*36367Ssklower /* 25*36367Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36367Ssklower */ 27*36367Ssklower /* $Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $ */ 28*36367Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_arp.c,v $ */ 29*36367Ssklower 30*36367Ssklower #ifndef lint 31*36367Ssklower static char *rcsid = "$Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $"; 32*36367Ssklower #endif lint 33*36367Ssklower 34*36367Ssklower #ifdef ISO 35*36367Ssklower 36*36367Ssklower #include "../h/types.h" 37*36367Ssklower #include "../h/param.h" 38*36367Ssklower #include "../h/mbuf.h" 39*36367Ssklower #include "../h/domain.h" 40*36367Ssklower #include "../h/protosw.h" 41*36367Ssklower #include "../h/socket.h" 42*36367Ssklower #include "../h/socketvar.h" 43*36367Ssklower #include "../h/errno.h" 44*36367Ssklower #include "../h/ioctl.h" 45*36367Ssklower 46*36367Ssklower #include "../net/if.h" 47*36367Ssklower #include "../net/route.h" 48*36367Ssklower 49*36367Ssklower #include "../netiso/iso.h" 50*36367Ssklower #include "../netiso/iso_var.h" 51*36367Ssklower #include "../netiso/iso_map.h" 52*36367Ssklower #include "../netiso/iso_snpac.h" 53*36367Ssklower #include "../netiso/clnp.h" 54*36367Ssklower #include "../netiso/clnp_stat.h" 55*36367Ssklower #include "../netiso/argo_debug.h" 56*36367Ssklower 57*36367Ssklower #define MAPTAB_BSIZ 20 /* bucket size */ 58*36367Ssklower #define MAPTAB_NB 13 /* number of buckets */ 59*36367Ssklower #define MAPTAB_SIZE (MAPTAB_BSIZ * MAPTAB_NB) 60*36367Ssklower struct maptab iso_maptab[MAPTAB_SIZE]; 61*36367Ssklower int iso_maptab_size = MAPTAB_SIZE; /* for isomap command */ 62*36367Ssklower 63*36367Ssklower #define MAPTAB_HASH(addr) \ 64*36367Ssklower (((u_long) iso_hashchar(addr, addr->isoa_len)) % MAPTAB_NB) 65*36367Ssklower 66*36367Ssklower #define MAPTAB_LOOK(at,addr) { \ 67*36367Ssklower register n; \ 68*36367Ssklower at = &iso_maptab[MAPTAB_HASH(addr) * MAPTAB_BSIZ]; \ 69*36367Ssklower for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) \ 70*36367Ssklower if ((at->map_valid) && (iso_addrmatch1(&at->map_isoa, addr))) \ 71*36367Ssklower break; \ 72*36367Ssklower if (n >= MAPTAB_BSIZ) \ 73*36367Ssklower at = 0; \ 74*36367Ssklower } 75*36367Ssklower 76*36367Ssklower /* 77*36367Ssklower * FUNCTION: clnp_arpresolve 78*36367Ssklower * 79*36367Ssklower * PURPOSE: Resolve a clnp address into hardware ethernet addr. 80*36367Ssklower * 81*36367Ssklower * RETURNS: 1 if addr is resolved 82*36367Ssklower * 0 if addr is unknown 83*36367Ssklower * 84*36367Ssklower * SIDE EFFECTS: 85*36367Ssklower * 86*36367Ssklower * NOTES: This is a hack. If the address is local, then 87*36367Ssklower * the packet is put on the loopback driver. Otherwise, 88*36367Ssklower * if a translation is found, that ethernet address is 89*36367Ssklower * returned. Otherwise, the packet is dropped. Thus, 90*36367Ssklower * each translation must be placed (by hand) in the 91*36367Ssklower * tables (see isomap(8)). 92*36367Ssklower * TODO: should this map stuff be a critical section? 93*36367Ssklower */ 94*36367Ssklower clnp_arpresolve(ifp, m, dst, edst) 95*36367Ssklower struct ifnet *ifp; /* outgoing interface */ 96*36367Ssklower struct mbuf *m; /* pkt */ 97*36367Ssklower struct sockaddr_iso *dst; /* destination */ 98*36367Ssklower char *edst; /* RESULT: ethernet address */ 99*36367Ssklower { 100*36367Ssklower extern struct ifnet loif; /* loopback interface */ 101*36367Ssklower struct maptab *at; /* ptr to map table entry */ 102*36367Ssklower struct iso_addr *destiso; /* destination iso addr */ 103*36367Ssklower 104*36367Ssklower destiso = &dst->siso_addr; 105*36367Ssklower 106*36367Ssklower if (destiso->isoa_afi == AFI_SNA) { 107*36367Ssklower /* 108*36367Ssklower * This is a subnetwork address. Return it immediately 109*36367Ssklower */ 110*36367Ssklower int sna_len; 111*36367Ssklower 112*36367Ssklower IFDEBUG(D_ESISOUTPUT) 113*36367Ssklower printf("clnp_arpresolve: return SN address\n"); 114*36367Ssklower ENDDEBUG 115*36367Ssklower 116*36367Ssklower sna_len = destiso->isoa_len - 1; /* subtract size of AFI */ 117*36367Ssklower if (sna_len != 6) { 118*36367Ssklower IFDEBUG(D_ESISOUTPUT) 119*36367Ssklower printf("clnp_arpresolve: SN len is bad (%d)\n", sna_len); 120*36367Ssklower ENDDEBUG 121*36367Ssklower return(-1); 122*36367Ssklower } 123*36367Ssklower bcopy((caddr_t) destiso->sna_idi, (caddr_t)edst, sna_len); 124*36367Ssklower return (1); 125*36367Ssklower } 126*36367Ssklower 127*36367Ssklower IFDEBUG(D_ETHER) 128*36367Ssklower printf("clnp_arpresolve: resolving %s\n", clnp_iso_addrp(destiso)); 129*36367Ssklower ENDDEBUG 130*36367Ssklower 131*36367Ssklower /* if for us, use software loopback driver if up */ 132*36367Ssklower if (clnp_ours(destiso)) { 133*36367Ssklower IFDEBUG(D_ETHER) 134*36367Ssklower printf("clnp_arpresolve: local destination\n"); 135*36367Ssklower ENDDEBUG 136*36367Ssklower if (loif.if_flags & IFF_UP) { 137*36367Ssklower IFDEBUG(D_ETHER) 138*36367Ssklower printf("clnp_arpresolve: calling looutput\n"); 139*36367Ssklower ENDDEBUG 140*36367Ssklower (void) looutput(&loif, m, (struct sockaddr *)dst); 141*36367Ssklower /* 142*36367Ssklower * The packet has already been sent and freed. 143*36367Ssklower */ 144*36367Ssklower return (0); 145*36367Ssklower } 146*36367Ssklower } 147*36367Ssklower 148*36367Ssklower IFDEBUG(D_ETHER) 149*36367Ssklower printf("clnp_arpresolve: NON-local destination\n"); 150*36367Ssklower ENDDEBUG 151*36367Ssklower 152*36367Ssklower /* 153*36367Ssklower * packet is not for us, check static map table for an entry 154*36367Ssklower * This does not need to be a critical section because the 155*36367Ssklower * table is not dynamically updated, except by a call to 156*36367Ssklower * isomap(8) 157*36367Ssklower */ 158*36367Ssklower MAPTAB_LOOK(at, destiso); 159*36367Ssklower if (at == 0) { /* not found */ 160*36367Ssklower m_freem(m); 161*36367Ssklower return (-1); 162*36367Ssklower } else { 163*36367Ssklower bcopy((caddr_t)at->map_enaddr, (caddr_t)edst, sizeof(at->map_enaddr)); 164*36367Ssklower return (1); 165*36367Ssklower } 166*36367Ssklower } 167*36367Ssklower 168*36367Ssklower /* 169*36367Ssklower * FUNCTION: isomap_new 170*36367Ssklower * 171*36367Ssklower * PURPOSE: create a new entry in the iso address to ethernet 172*36367Ssklower * address table 173*36367Ssklower * 174*36367Ssklower * RETURNS: pointer to newest entry, or NULL if none can be found 175*36367Ssklower * 176*36367Ssklower * SIDE EFFECTS: 177*36367Ssklower * 178*36367Ssklower * NOTES: TODO: timeout old entries 179*36367Ssklower */ 180*36367Ssklower struct maptab * 181*36367Ssklower isomap_new(isoa) 182*36367Ssklower struct iso_addr *isoa; /* iso address to enter into table */ 183*36367Ssklower { 184*36367Ssklower register struct maptab *at; 185*36367Ssklower register int n; 186*36367Ssklower 187*36367Ssklower at = &iso_maptab[MAPTAB_HASH(isoa) * MAPTAB_BSIZ]; 188*36367Ssklower for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) { 189*36367Ssklower 190*36367Ssklower IFDEBUG (D_IOCTL) 191*36367Ssklower printf("isomap_new: at x%x ", at); 192*36367Ssklower 193*36367Ssklower if (at->map_valid) { 194*36367Ssklower int i; 195*36367Ssklower 196*36367Ssklower printf("(valid) %s ", clnp_iso_addrp(&at->map_isoa)); 197*36367Ssklower for (i=0; i<6; i++) 198*36367Ssklower printf("%x%c", at->map_enaddr[i], i < 5 ? ':' : '\n'); 199*36367Ssklower } else { 200*36367Ssklower printf("invalid\n"); 201*36367Ssklower } 202*36367Ssklower ENDDEBUG 203*36367Ssklower 204*36367Ssklower if (!at->map_valid) /* found unused slot */ 205*36367Ssklower return at; 206*36367Ssklower } 207*36367Ssklower return NULL; 208*36367Ssklower } 209*36367Ssklower 210*36367Ssklower /* 211*36367Ssklower * FUNCTION: isomap_free 212*36367Ssklower * 213*36367Ssklower * PURPOSE: free an entry in the iso address map table 214*36367Ssklower * 215*36367Ssklower * RETURNS: nothing 216*36367Ssklower * 217*36367Ssklower * SIDE EFFECTS: 218*36367Ssklower * 219*36367Ssklower * NOTES: 220*36367Ssklower */ 221*36367Ssklower isomap_free(at) 222*36367Ssklower register struct maptab *at; /* entry to free */ 223*36367Ssklower { 224*36367Ssklower at->map_valid = 0; 225*36367Ssklower } 226*36367Ssklower 227*36367Ssklower /* 228*36367Ssklower * FUNCTION: isomap_ioctl 229*36367Ssklower * 230*36367Ssklower * PURPOSE: handle ioctls to change the iso address map 231*36367Ssklower * 232*36367Ssklower * RETURNS: unix error code 233*36367Ssklower * 234*36367Ssklower * SIDE EFFECTS: changes the maptab table declared above. 235*36367Ssklower * 236*36367Ssklower * NOTES: 237*36367Ssklower */ 238*36367Ssklower isomap_ioctl(cmd, data) 239*36367Ssklower int cmd; /* ioctl to process */ 240*36367Ssklower caddr_t data; /* data for the cmd */ 241*36367Ssklower { 242*36367Ssklower register struct arpreq *ar = (struct arpreq *)data; 243*36367Ssklower register struct maptab *at; 244*36367Ssklower register struct sockaddr_iso *siso; 245*36367Ssklower register struct iso_addr *isoa; 246*36367Ssklower 247*36367Ssklower /* 248*36367Ssklower * only process commands for the ISO address family 249*36367Ssklower */ 250*36367Ssklower if (ar->arp_pa.sa_family != AF_ISO) 251*36367Ssklower return(EAFNOSUPPORT); 252*36367Ssklower 253*36367Ssklower /* look up this address in table */ 254*36367Ssklower siso = (struct sockaddr_iso *)&ar->arp_pa; 255*36367Ssklower isoa = &siso->siso_addr; 256*36367Ssklower 257*36367Ssklower IFDEBUG (D_IOCTL) 258*36367Ssklower int i; 259*36367Ssklower 260*36367Ssklower printf("isomap_ioctl: "); 261*36367Ssklower switch(cmd) { 262*36367Ssklower case SIOCSISOMAP: printf("set"); break; 263*36367Ssklower case SIOCDISOMAP: printf("delete"); break; 264*36367Ssklower case SIOCGISOMAP: printf("get"); break; 265*36367Ssklower } 266*36367Ssklower printf(" %s to ", clnp_iso_addrp(isoa)); 267*36367Ssklower for (i=0; i<6; i++) 268*36367Ssklower printf("%x%c", ar->arp_ha.sa_data[i], i < 5 ? ':' : '\n'); 269*36367Ssklower ENDDEBUG 270*36367Ssklower 271*36367Ssklower MAPTAB_LOOK(at, isoa); 272*36367Ssklower if (at == NULL) { /* not found */ 273*36367Ssklower if (cmd != SIOCSISOMAP) 274*36367Ssklower return(ENXIO); 275*36367Ssklower 276*36367Ssklower /* TODO: what if setting and net is not directly attached */ 277*36367Ssklower } 278*36367Ssklower 279*36367Ssklower switch(cmd) { 280*36367Ssklower case SIOCSISOMAP: /* set entry */ 281*36367Ssklower if (at == NULL) { 282*36367Ssklower at = isomap_new(isoa); 283*36367Ssklower if (at == NULL) 284*36367Ssklower return(ENOBUFS); 285*36367Ssklower } 286*36367Ssklower bcopy((caddr_t)isoa, (caddr_t)&at->map_isoa, 287*36367Ssklower sizeof (struct iso_addr)); 288*36367Ssklower bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->map_enaddr, 289*36367Ssklower sizeof(at->map_enaddr)); 290*36367Ssklower at->map_valid++; 291*36367Ssklower break; 292*36367Ssklower 293*36367Ssklower case SIOCDISOMAP: /* delete entry */ 294*36367Ssklower isomap_free(at); 295*36367Ssklower break; 296*36367Ssklower 297*36367Ssklower case SIOCGISOMAP: /* get entry */ 298*36367Ssklower bcopy((caddr_t)at->map_enaddr, (caddr_t)ar->arp_ha.sa_data, 299*36367Ssklower sizeof(at->map_enaddr)); 300*36367Ssklower } 301*36367Ssklower return(0); 302*36367Ssklower } 303*36367Ssklower #endif ISO 304