1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: * 12: * @(#)if_ether.c 7.6 (Berkeley) 12/7/87 13: */ 14: 15: /* 16: * Ethernet address resolution protocol. 17: * TODO: 18: * run at splnet (add ARP protocol intr.) 19: * link entries onto hash chains, keep free list 20: * add "inuse/lock" bit (or ref. count) along with valid bit 21: */ 22: 23: #include "ether.h" 24: #if NETHER > 0 25: 26: #include "param.h" 27: #include "systm.h" 28: #include "mbuf.h" 29: #include "socket.h" 30: #include "time.h" 31: #include "kernel.h" 32: #include "errno.h" 33: #include "ioctl.h" 34: #include "syslog.h" 35: 36: #include "domain.h" 37: #include "protosw.h" 38: #include "../net/if.h" 39: #include "in.h" 40: #include "in_systm.h" 41: #include "ip.h" 42: #include "if_ether.h" 43: 44: #define ARPTAB_BSIZ 5 /* bucket size */ 45: #define ARPTAB_NB 13 /* number of buckets */ 46: #define ARPTAB_SIZE (ARPTAB_BSIZ * ARPTAB_NB) 47: struct arptab arptab[ARPTAB_SIZE]; 48: int arptab_size = ARPTAB_SIZE; /* for arp command */ 49: 50: /* 51: * ARP trailer negotiation. Trailer protocol is not IP specific, 52: * but ARP request/response use IP addresses. 53: */ 54: #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL 55: 56: #define ARPTAB_HASH(a) \ 57: ((short)((((a) >> 16) ^ (a)) & 0x7fff) % ARPTAB_NB) 58: 59: #define ARPTAB_LOOK(at,addr) { \ 60: register n; \ 61: at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \ 62: for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \ 63: if (at->at_iaddr.s_addr == addr) \ 64: break; \ 65: if (n >= ARPTAB_BSIZ) \ 66: at = 0; \ 67: } 68: 69: /* timer values */ 70: #define ARPT_AGE (60*1) /* aging timer, 1 min. */ 71: #define ARPT_KILLC 20 /* kill completed entry in 20 mins. */ 72: #define ARPT_KILLI 3 /* kill incomplete entry in 3 minutes */ 73: 74: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 75: extern struct ifnet loif; 76: extern int hz; 77: 78: /* 79: * Timeout routine. Age arp_tab entries once a minute. 80: */ 81: arptimer() 82: { 83: register struct arptab *at; 84: register i; 85: 86: TIMEOUT(arptimer, (caddr_t)0, ARPT_AGE * hz); 87: at = &arptab[0]; 88: for (i = 0; i < ARPTAB_SIZE; i++, at++) { 89: if (at->at_flags == 0 || (at->at_flags & ATF_PERM)) 90: continue; 91: if (++at->at_timer < ((at->at_flags&ATF_COM) ? 92: ARPT_KILLC : ARPT_KILLI)) 93: continue; 94: /* timer has expired, clear entry */ 95: arptfree(at); 96: } 97: } 98: 99: /* 100: * Broadcast an ARP packet, asking who has addr on interface ac. 101: */ 102: arpwhohas(ac, addr) 103: register struct arpcom *ac; 104: struct in_addr *addr; 105: { 106: register struct mbuf *m; 107: register struct ether_header *eh; 108: register struct ether_arp *ea; 109: struct sockaddr sa; 110: 111: if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) 112: return; 113: m->m_len = sizeof *ea; 114: m->m_off = MMAXOFF - m->m_len; 115: ea = mtod(m, struct ether_arp *); 116: eh = (struct ether_header *)sa.sa_data; 117: bzero((caddr_t)ea, sizeof (*ea)); 118: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 119: sizeof(eh->ether_dhost)); 120: eh->ether_type = ETHERTYPE_ARP; /* if_output will swap */ 121: ea->arp_hrd = htons(ARPHRD_ETHER); 122: ea->arp_pro = htons(ETHERTYPE_IP); 123: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ 124: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ 125: ea->arp_op = htons(ARPOP_REQUEST); 126: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, 127: sizeof(ea->arp_sha)); 128: bcopy((caddr_t)&ac->ac_ipaddr, (caddr_t)ea->arp_spa, 129: sizeof(ea->arp_spa)); 130: bcopy((caddr_t)addr, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa)); 131: sa.sa_family = AF_UNSPEC; 132: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa); 133: } 134: 135: int useloopback = 1; /* use loopback interface for local traffic */ 136: 137: /* 138: * Resolve an IP address into an ethernet address. If success, 139: * desten is filled in. If there is no entry in arptab, 140: * set one up and broadcast a request for the IP address. 141: * Hold onto this mbuf and resend it once the address 142: * is finally resolved. A return value of 1 indicates 143: * that desten has been filled in and the packet should be sent 144: * normally; a 0 return indicates that the packet has been 145: * taken over here, either now or for later transmission. 146: * 147: * We do some (conservative) locking here at splimp, since 148: * arptab is also altered from input interrupt service (ecintr/ilintr 149: * calls arpinput when ETHERTYPE_ARP packets come in). 150: */ 151: arpresolve(ac, m, destip, desten, usetrailers) 152: register struct arpcom *ac; 153: struct mbuf *m; 154: register struct in_addr *destip; 155: register u_char *desten; 156: int *usetrailers; 157: { 158: register struct arptab *at; 159: struct sockaddr_in sin; 160: u_long lna; 161: int s; 162: 163: *usetrailers = 0; 164: if (in_broadcast(*destip)) { /* broadcast address */ 165: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten, 166: sizeof(etherbroadcastaddr)); 167: return (1); 168: } 169: lna = in_lnaof(*destip); 170: /* if for us, use software loopback driver if up */ 171: if (destip->s_addr == ac->ac_ipaddr.s_addr) { 172: /* 173: * This test used to be 174: * if (loif.if_flags & IFF_UP) 175: * It allowed local traffic to be forced 176: * through the hardware by configuring the loopback down. 177: * However, it causes problems during network configuration 178: * for boards that can't receive packets they send. 179: * It is now necessary to clear "useloopback" 180: * to force traffic out to the hardware. 181: */ 182: if (useloopback) { 183: sin.sin_family = AF_INET; 184: sin.sin_addr = *destip; 185: (void) looutput(&loif, m, (struct sockaddr *)&sin); 186: /* 187: * The packet has already been sent and freed. 188: */ 189: return (0); 190: } else { 191: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 192: sizeof(ac->ac_enaddr)); 193: return (1); 194: } 195: } 196: s = splimp(); 197: ARPTAB_LOOK(at, destip->s_addr); 198: if (at == 0) { /* not found */ 199: if (ac->ac_if.if_flags & IFF_NOARP) { 200: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3); 201: desten[3] = (lna >> 16) & 0x7f; 202: desten[4] = (lna >> 8) & 0xff; 203: desten[5] = lna & 0xff; 204: splx(s); 205: return (1); 206: } else { 207: at = arptnew(destip); 208: if (at == 0) 209: panic("arpresolve: no free entry"); 210: at->at_hold = m; 211: arpwhohas(ac, destip); 212: splx(s); 213: return (0); 214: } 215: } 216: at->at_timer = 0; /* restart the timer */ 217: if (at->at_flags & ATF_COM) { /* entry IS complete */ 218: bcopy((caddr_t)at->at_enaddr, (caddr_t)desten, 219: sizeof(at->at_enaddr)); 220: #ifdef I_WANT_MY_MACHINE_TO_CRASH 221: if (at->at_flags & ATF_USETRAILERS) 222: *usetrailers = 1; 223: #endif 224: splx(s); 225: return (1); 226: } 227: /* 228: * There is an arptab entry, but no ethernet address 229: * response yet. Replace the held mbuf with this 230: * latest one. 231: */ 232: if (at->at_hold) 233: m_freem(at->at_hold); 234: at->at_hold = m; 235: arpwhohas(ac, destip); /* ask again */ 236: splx(s); 237: return (0); 238: } 239: 240: /* 241: * Called from 10 Mb/s Ethernet interrupt handlers 242: * when ether packet type ETHERTYPE_ARP 243: * is received. Common length and type checks are done here, 244: * then the protocol-specific routine is called. 245: */ 246: arpinput(ac, m) 247: struct arpcom *ac; 248: struct mbuf *m; 249: { 250: register struct arphdr *ar; 251: 252: if (ac->ac_if.if_flags & IFF_NOARP) 253: goto out; 254: IF_ADJ(m); 255: if (m->m_len < sizeof(struct arphdr)) 256: goto out; 257: ar = mtod(m, struct arphdr *); 258: if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) 259: goto out; 260: if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln) 261: goto out; 262: 263: switch (ntohs(ar->ar_pro)) { 264: 265: case ETHERTYPE_IP: 266: case ETHERTYPE_IPTRAILERS: 267: in_arpinput(ac, m); 268: return; 269: 270: default: 271: break; 272: } 273: out: 274: m_freem(m); 275: } 276: 277: /* 278: * ARP for Internet protocols on 10 Mb/s Ethernet. 279: * Algorithm is that given in RFC 826. 280: * In addition, a sanity check is performed on the sender 281: * protocol address, to catch impersonators. 282: * We also handle negotiations for use of trailer protocol: 283: * ARP replies for protocol type ETHERTYPE_TRAIL are sent 284: * along with IP replies if we want trailers sent to us, 285: * and also send them in response to IP replies. 286: * This allows either end to announce the desire to receive 287: * trailer packets. 288: * We reply to requests for ETHERTYPE_TRAIL protocol as well, 289: * but don't normally send requests. 290: */ 291: in_arpinput(ac, m) 292: register struct arpcom *ac; 293: struct mbuf *m; 294: { 295: register struct ether_arp *ea; 296: struct ether_header *eh; 297: register struct arptab *at; /* same as "merge" flag */ 298: struct mbuf *mcopy = 0; 299: struct sockaddr_in sin; 300: struct sockaddr sa; 301: struct in_addr isaddr, itaddr, myaddr; 302: int proto, op, s, completed = 0; 303: 304: myaddr = ac->ac_ipaddr; 305: ea = mtod(m, struct ether_arp *); 306: proto = ntohs(ea->arp_pro); 307: op = ntohs(ea->arp_op); 308: bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr)); 309: bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr)); 310: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr, 311: sizeof (ea->arp_sha))) 312: goto out; /* it's from me, ignore it. */ 313: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr, 314: sizeof (ea->arp_sha))) { 315: printf("arp: ether address is broadcast for IP address %x!\n", 316: ntohl(isaddr.s_addr)); 317: goto out; 318: } 319: if (isaddr.s_addr == myaddr.s_addr) { 320: printf("%s: %s\n", 321: "duplicate IP address!! sent from ethernet address", 322: ether_sprintf(ea->arp_sha)); 323: itaddr = myaddr; 324: if (op == ARPOP_REQUEST) 325: goto reply; 326: goto out; 327: } 328: s = splimp(); 329: ARPTAB_LOOK(at, isaddr.s_addr); 330: if (at) { 331: bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr, 332: sizeof(ea->arp_sha)); 333: if ((at->at_flags & ATF_COM) == 0) 334: completed = 1; 335: at->at_flags |= ATF_COM; 336: if (at->at_hold) { 337: sin.sin_family = AF_INET; 338: sin.sin_addr = isaddr; 339: (*ac->ac_if.if_output)(&ac->ac_if, 340: at->at_hold, (struct sockaddr *)&sin); 341: at->at_hold = 0; 342: } 343: } 344: if (at == 0 && itaddr.s_addr == myaddr.s_addr) { 345: /* ensure we have a table entry */ 346: if (at = arptnew(&isaddr)) { 347: bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr, 348: sizeof(ea->arp_sha)); 349: completed = 1; 350: at->at_flags |= ATF_COM; 351: } 352: } 353: splx(s); 354: reply: 355: switch (proto) { 356: 357: case ETHERTYPE_IPTRAILERS: 358: /* partner says trailers are OK */ 359: if (at) 360: at->at_flags |= ATF_USETRAILERS; 361: /* 362: * Reply to request iff we want trailers. 363: */ 364: if (op != ARPOP_REQUEST || ac->ac_if.if_flags & IFF_NOTRAILERS) 365: goto out; 366: break; 367: 368: case ETHERTYPE_IP: 369: /* 370: * Reply if this is an IP request, 371: * or if we want to send a trailer response. 372: * Send the latter only to the IP response 373: * that completes the current ARP entry. 374: */ 375: if (op != ARPOP_REQUEST && 376: (completed == 0 || ac->ac_if.if_flags & IFF_NOTRAILERS)) 377: goto out; 378: } 379: if (itaddr.s_addr == myaddr.s_addr) { 380: /* I am the target */ 381: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, 382: sizeof(ea->arp_sha)); 383: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, 384: sizeof(ea->arp_sha)); 385: } else { 386: ARPTAB_LOOK(at, itaddr.s_addr); 387: if (at == NULL || (at->at_flags & ATF_PUBL) == 0) 388: goto out; 389: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, 390: sizeof(ea->arp_sha)); 391: bcopy((caddr_t)at->at_enaddr, (caddr_t)ea->arp_sha, 392: sizeof(ea->arp_sha)); 393: } 394: 395: bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, 396: sizeof(ea->arp_spa)); 397: bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, 398: sizeof(ea->arp_spa)); 399: ea->arp_op = htons(ARPOP_REPLY); 400: /* 401: * If incoming packet was an IP reply, 402: * we are sending a reply for type IPTRAILERS. 403: * If we are sending a reply for type IP 404: * and we want to receive trailers, 405: * send a trailer reply as well. 406: */ 407: if (op == ARPOP_REPLY) 408: ea->arp_pro = htons(ETHERTYPE_IPTRAILERS); 409: else if (proto == ETHERTYPE_IP && 410: (ac->ac_if.if_flags & IFF_NOTRAILERS) == 0) 411: mcopy = m_copy(m, 0, (int)M_COPYALL); 412: eh = (struct ether_header *)sa.sa_data; 413: bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost, 414: sizeof(eh->ether_dhost)); 415: eh->ether_type = ETHERTYPE_ARP; 416: sa.sa_family = AF_UNSPEC; 417: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa); 418: if (mcopy) { 419: ea = mtod(mcopy, struct ether_arp *); 420: ea->arp_pro = htons(ETHERTYPE_IPTRAILERS); 421: (*ac->ac_if.if_output)(&ac->ac_if, mcopy, &sa); 422: } 423: return; 424: out: 425: m_freem(m); 426: return; 427: } 428: 429: /* 430: * Free an arptab entry. 431: */ 432: arptfree(at) 433: register struct arptab *at; 434: { 435: int s = splimp(); 436: 437: if (at->at_hold) 438: m_freem(at->at_hold); 439: at->at_hold = 0; 440: at->at_timer = at->at_flags = 0; 441: at->at_iaddr.s_addr = 0; 442: splx(s); 443: } 444: 445: /* 446: * Enter a new address in arptab, pushing out the oldest entry 447: * from the bucket if there is no room. 448: * This always succeeds since no bucket can be completely filled 449: * with permanent entries (except from arpioctl when testing whether 450: * another permanent entry will fit). 451: * MUST BE CALLED AT SPLIMP. 452: */ 453: struct arptab * 454: arptnew(addr) 455: struct in_addr *addr; 456: { 457: register n; 458: int oldest = -1; 459: register struct arptab *at, *ato = NULL; 460: static int first = 1; 461: 462: if (first) { 463: first = 0; 464: TIMEOUT(arptimer, (caddr_t)0, hz); 465: } 466: at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ]; 467: for (n = 0; n < ARPTAB_BSIZ; n++,at++) { 468: if (at->at_flags == 0) 469: goto out; /* found an empty entry */ 470: if (at->at_flags & ATF_PERM) 471: continue; 472: if ((int) at->at_timer > oldest) { 473: oldest = at->at_timer; 474: ato = at; 475: } 476: } 477: if (ato == NULL) 478: return (NULL); 479: at = ato; 480: arptfree(at); 481: out: 482: at->at_iaddr = *addr; 483: at->at_flags = ATF_INUSE; 484: return (at); 485: } 486: 487: arpioctl(cmd, data) 488: int cmd; 489: caddr_t data; 490: { 491: register struct arpreq *ar = (struct arpreq *)data; 492: register struct arptab *at; 493: register struct sockaddr_in *sin; 494: int s; 495: 496: if (ar->arp_pa.sa_family != AF_INET || 497: ar->arp_ha.sa_family != AF_UNSPEC) 498: return (EAFNOSUPPORT); 499: sin = (struct sockaddr_in *)&ar->arp_pa; 500: s = splimp(); 501: ARPTAB_LOOK(at, sin->sin_addr.s_addr); 502: if (at == NULL) { /* not found */ 503: if (cmd != SIOCSARP) { 504: splx(s); 505: return (ENXIO); 506: } 507: if (ifa_ifwithnet(&ar->arp_pa) == NULL) { 508: splx(s); 509: return (ENETUNREACH); 510: } 511: } 512: switch (cmd) { 513: 514: case SIOCSARP: /* set entry */ 515: if (at == NULL) { 516: at = arptnew(&sin->sin_addr); 517: if (at == NULL) { 518: splx(s); 519: return (EADDRNOTAVAIL); 520: } 521: if (ar->arp_flags & ATF_PERM) { 522: /* never make all entries in a bucket permanent */ 523: register struct arptab *tat; 524: 525: /* try to re-allocate */ 526: tat = arptnew(&sin->sin_addr); 527: if (tat == NULL) { 528: arptfree(at); 529: splx(s); 530: return (EADDRNOTAVAIL); 531: } 532: arptfree(tat); 533: } 534: } 535: bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->at_enaddr, 536: sizeof(at->at_enaddr)); 537: at->at_flags = ATF_COM | ATF_INUSE | 538: (ar->arp_flags & (ATF_PERM|ATF_PUBL|ATF_USETRAILERS)); 539: at->at_timer = 0; 540: break; 541: 542: case SIOCDARP: /* delete entry */ 543: arptfree(at); 544: break; 545: 546: case SIOCGARP: /* get entry */ 547: bcopy((caddr_t)at->at_enaddr, (caddr_t)ar->arp_ha.sa_data, 548: sizeof(at->at_enaddr)); 549: ar->arp_flags = at->at_flags; 550: break; 551: } 552: splx(s); 553: return (0); 554: } 555: 556: /* 557: * Convert Ethernet address to printable (loggable) representation. 558: */ 559: char * 560: ether_sprintf(ap) 561: register u_char *ap; 562: { 563: register i; 564: static char etherbuf[18]; 565: register char *cp = etherbuf; 566: static char digits[] = "0123456789abcdef"; 567: 568: for (i = 0; i < 6; i++) { 569: *cp++ = digits[*ap >> 4]; 570: *cp++ = digits[*ap++ & 0xf]; 571: *cp++ = ':'; 572: } 573: *--cp = 0; 574: return (etherbuf); 575: } 576: #endif