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