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