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