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