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