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.8 (Berkeley) 10/12/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 "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 (*ac->ac_if.if_output)(&ac->ac_if, m, &sa); 138 } 139 140 int useloopback = 1; /* use loopback interface for local traffic */ 141 142 /* 143 * Resolve an IP address into an ethernet address. If success, 144 * desten is filled in. If there is no entry in arptab, 145 * set one up and broadcast a request for the IP address. 146 * Hold onto this mbuf and resend it once the address 147 * is finally resolved. A return value of 1 indicates 148 * that desten has been filled in and the packet should be sent 149 * normally; a 0 return indicates that the packet has been 150 * taken over here, either now or for later transmission. 151 * 152 * We do some (conservative) locking here at splimp, since 153 * arptab is also altered from input interrupt service (ecintr/ilintr 154 * calls arpinput when ETHERTYPE_ARP packets come in). 155 */ 156 arpresolve(ac, m, destip, desten, usetrailers) 157 register struct arpcom *ac; 158 struct mbuf *m; 159 register struct in_addr *destip; 160 register u_char *desten; 161 int *usetrailers; 162 { 163 register struct arptab *at; 164 struct sockaddr_in sin; 165 u_long lna; 166 int s; 167 168 *usetrailers = 0; 169 if (m->m_flags & M_BCAST) { /* broadcast */ 170 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten, 171 sizeof(etherbroadcastaddr)); 172 return (1); 173 } 174 lna = in_lnaof(*destip); 175 /* if for us, use software loopback driver if up */ 176 if (destip->s_addr == ac->ac_ipaddr.s_addr) { 177 /* 178 * This test used to be 179 * if (loif.if_flags & IFF_UP) 180 * It allowed local traffic to be forced 181 * through the hardware by configuring the loopback down. 182 * However, it causes problems during network configuration 183 * for boards that can't receive packets they send. 184 * It is now necessary to clear "useloopback" 185 * to force traffic out to the hardware. 186 */ 187 if (useloopback) { 188 sin.sin_family = AF_INET; 189 sin.sin_addr = *destip; 190 (void) looutput(&loif, m, (struct sockaddr *)&sin); 191 /* 192 * The packet has already been sent and freed. 193 */ 194 return (0); 195 } else { 196 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 197 sizeof(ac->ac_enaddr)); 198 return (1); 199 } 200 } 201 s = splimp(); 202 ARPTAB_LOOK(at, destip->s_addr); 203 if (at == 0) { /* not found */ 204 if (ac->ac_if.if_flags & IFF_NOARP) { 205 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3); 206 desten[3] = (lna >> 16) & 0x7f; 207 desten[4] = (lna >> 8) & 0xff; 208 desten[5] = lna & 0xff; 209 splx(s); 210 return (1); 211 } else { 212 at = arptnew(destip); 213 if (at == 0) 214 panic("arpresolve: no free entry"); 215 at->at_hold = m; 216 arpwhohas(ac, destip); 217 splx(s); 218 return (0); 219 } 220 } 221 at->at_timer = 0; /* restart the timer */ 222 if (at->at_flags & ATF_COM) { /* entry IS complete */ 223 bcopy((caddr_t)at->at_enaddr, (caddr_t)desten, 224 sizeof(at->at_enaddr)); 225 if (at->at_flags & ATF_USETRAILERS) 226 *usetrailers = 1; 227 splx(s); 228 return (1); 229 } 230 /* 231 * There is an arptab entry, but no ethernet address 232 * response yet. Replace the held mbuf with this 233 * latest one. 234 */ 235 if (at->at_hold) 236 m_freem(at->at_hold); 237 at->at_hold = m; 238 arpwhohas(ac, destip); /* ask again */ 239 splx(s); 240 return (0); 241 } 242 243 /* 244 * Called from 10 Mb/s Ethernet interrupt handlers 245 * when ether packet type ETHERTYPE_ARP 246 * is received. Common length and type checks are done here, 247 * then the protocol-specific routine is called. 248 */ 249 arpinput(ac, m) 250 struct arpcom *ac; 251 struct mbuf *m; 252 { 253 register struct arphdr *ar; 254 255 if (ac->ac_if.if_flags & IFF_NOARP) 256 goto out; 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