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