1 /* $OpenBSD: if_ether.c,v 1.205 2016/04/27 14:47:27 mpi Exp $ */ 2 /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)if_ether.c 8.1 (Berkeley) 6/10/93 33 */ 34 35 /* 36 * Ethernet address resolution protocol. 37 * TODO: 38 * add "inuse/lock" bit (or ref. count) along with valid bit 39 */ 40 41 #include "carp.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/mbuf.h> 46 #include <sys/socket.h> 47 #include <sys/timeout.h> 48 #include <sys/kernel.h> 49 #include <sys/syslog.h> 50 #include <sys/queue.h> 51 #include <sys/pool.h> 52 53 #include <net/if.h> 54 #include <net/if_var.h> 55 #include <net/if_dl.h> 56 #include <net/route.h> 57 #include <net/if_types.h> 58 #include <net/netisr.h> 59 60 #include <netinet/in.h> 61 #include <netinet/in_var.h> 62 #include <netinet/if_ether.h> 63 #if NCARP > 0 64 #include <netinet/ip_carp.h> 65 #endif 66 67 struct llinfo_arp { 68 LIST_ENTRY(llinfo_arp) la_list; 69 struct rtentry *la_rt; /* backpointer to rtentry */ 70 long la_asked; /* last time we QUERIED */ 71 struct mbuf_list la_ml; /* packet hold queue */ 72 }; 73 #define LA_HOLD_QUEUE 10 74 #define LA_HOLD_TOTAL 100 75 76 /* timer values */ 77 int arpt_prune = (5*60*1); /* walk list every 5 minutes */ 78 int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ 79 int arpt_down = 20; /* once declared down, don't send for 20 secs */ 80 81 void arptfree(struct rtentry *); 82 void arptimer(void *); 83 struct rtentry *arplookup(u_int32_t, int, int, u_int); 84 void in_arpinput(struct mbuf *); 85 void in_revarpinput(struct mbuf *); 86 87 LIST_HEAD(, llinfo_arp) arp_list; 88 struct pool arp_pool; /* pool for llinfo_arp structures */ 89 int arp_maxtries = 5; 90 int arpinit_done; 91 int la_hold_total; 92 93 #ifdef NFSCLIENT 94 /* revarp state */ 95 struct in_addr revarp_myip, revarp_srvip; 96 int revarp_finished; 97 unsigned int revarp_ifidx; 98 #endif /* NFSCLIENT */ 99 100 /* 101 * Timeout routine. Age arp_tab entries periodically. 102 */ 103 /* ARGSUSED */ 104 void 105 arptimer(void *arg) 106 { 107 struct timeout *to = (struct timeout *)arg; 108 int s; 109 struct llinfo_arp *la, *nla; 110 111 s = splsoftnet(); 112 timeout_add_sec(to, arpt_prune); 113 LIST_FOREACH_SAFE(la, &arp_list, la_list, nla) { 114 struct rtentry *rt = la->la_rt; 115 116 if (rt->rt_expire && rt->rt_expire <= time_second) 117 arptfree(rt); /* timer has expired; clear */ 118 } 119 splx(s); 120 } 121 122 void 123 arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) 124 { 125 struct sockaddr *gate = rt->rt_gateway; 126 struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; 127 struct ifaddr *ifa; 128 129 if (!arpinit_done) { 130 static struct timeout arptimer_to; 131 132 arpinit_done = 1; 133 pool_init(&arp_pool, sizeof(struct llinfo_arp), 0, 0, 0, "arp", 134 NULL); 135 /* 136 * We generate expiration times from time.tv_sec 137 * so avoid accidently creating permanent routes. 138 */ 139 if (time_second == 0) { 140 time_second++; 141 } 142 143 timeout_set(&arptimer_to, arptimer, &arptimer_to); 144 timeout_add_sec(&arptimer_to, 1); 145 } 146 147 if (rt->rt_flags & (RTF_GATEWAY|RTF_BROADCAST)) 148 return; 149 150 switch (req) { 151 152 case RTM_ADD: 153 if (rt->rt_flags & RTF_CLONING || 154 ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la)) { 155 /* 156 * Give this route an expiration time, even though 157 * it's a "permanent" route, so that routes cloned 158 * from it do not need their expiration time set. 159 */ 160 rt->rt_expire = time_second; 161 if ((rt->rt_flags & RTF_CLONING) != 0) 162 break; 163 } 164 /* 165 * Announce a new entry if requested or warn the user 166 * if another station has this IP address. 167 */ 168 if (rt->rt_flags & (RTF_ANNOUNCE|RTF_LOCAL)) 169 arprequest(ifp, 170 &satosin(rt_key(rt))->sin_addr.s_addr, 171 &satosin(rt_key(rt))->sin_addr.s_addr, 172 (u_char *)LLADDR(satosdl(gate))); 173 /*FALLTHROUGH*/ 174 case RTM_RESOLVE: 175 if (gate->sa_family != AF_LINK || 176 gate->sa_len < sizeof(struct sockaddr_dl)) { 177 log(LOG_DEBUG, "%s: bad gateway value: %s\n", __func__, 178 ifp->if_xname); 179 break; 180 } 181 satosdl(gate)->sdl_type = ifp->if_type; 182 satosdl(gate)->sdl_index = ifp->if_index; 183 if (la != 0) 184 break; /* This happens on a route change */ 185 /* 186 * Case 2: This route may come from cloning, or a manual route 187 * add with a LL address. 188 */ 189 la = pool_get(&arp_pool, PR_NOWAIT | PR_ZERO); 190 rt->rt_llinfo = (caddr_t)la; 191 if (la == NULL) { 192 log(LOG_DEBUG, "%s: pool get failed\n", __func__); 193 break; 194 } 195 196 ml_init(&la->la_ml); 197 la->la_rt = rt; 198 rt->rt_flags |= RTF_LLINFO; 199 LIST_INSERT_HEAD(&arp_list, la, la_list); 200 201 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 202 if ((ifa->ifa_addr->sa_family == AF_INET) && 203 ifatoia(ifa)->ia_addr.sin_addr.s_addr == 204 satosin(rt_key(rt))->sin_addr.s_addr) 205 break; 206 } 207 if (ifa) { 208 KASSERT(ifa == rt->rt_ifa); 209 rt->rt_expire = 0; 210 } 211 break; 212 213 case RTM_DELETE: 214 if (la == NULL) 215 break; 216 LIST_REMOVE(la, la_list); 217 rt->rt_llinfo = 0; 218 rt->rt_flags &= ~RTF_LLINFO; 219 la_hold_total -= ml_purge(&la->la_ml); 220 pool_put(&arp_pool, la); 221 } 222 } 223 224 /* 225 * Broadcast an ARP request. Caller specifies: 226 * - arp header source ip address 227 * - arp header target ip address 228 * - arp header source ethernet address 229 */ 230 void 231 arprequest(struct ifnet *ifp, u_int32_t *sip, u_int32_t *tip, u_int8_t *enaddr) 232 { 233 struct mbuf *m; 234 struct ether_header *eh; 235 struct ether_arp *ea; 236 struct sockaddr sa; 237 238 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) 239 return; 240 m->m_len = sizeof(*ea); 241 m->m_pkthdr.len = sizeof(*ea); 242 m->m_pkthdr.ph_rtableid = ifp->if_rdomain; 243 MH_ALIGN(m, sizeof(*ea)); 244 ea = mtod(m, struct ether_arp *); 245 eh = (struct ether_header *)sa.sa_data; 246 memset(ea, 0, sizeof(*ea)); 247 memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost)); 248 eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */ 249 ea->arp_hrd = htons(ARPHRD_ETHER); 250 ea->arp_pro = htons(ETHERTYPE_IP); 251 ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ 252 ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ 253 ea->arp_op = htons(ARPOP_REQUEST); 254 memcpy(eh->ether_shost, enaddr, sizeof(eh->ether_shost)); 255 memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha)); 256 memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa)); 257 memcpy(ea->arp_tpa, tip, sizeof(ea->arp_tpa)); 258 sa.sa_family = pseudo_AF_HDRCMPLT; 259 sa.sa_len = sizeof(sa); 260 m->m_flags |= M_BCAST; 261 ifp->if_output(ifp, m, &sa, NULL); 262 } 263 264 /* 265 * Resolve an IP address into an ethernet address. If success, 266 * desten is filled in. If there is no entry in arptab, 267 * set one up and broadcast a request for the IP address. 268 * Hold onto this mbuf and resend it once the address 269 * is finally resolved. A return value of 0 indicates 270 * that desten has been filled in and the packet should be sent 271 * normally; A return value of EAGAIN indicates that the packet 272 * has been taken over here, either now or for later transmission. 273 * Any other return value indicates an error. 274 */ 275 int 276 arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, 277 struct sockaddr *dst, u_char *desten) 278 { 279 struct arpcom *ac = (struct arpcom *)ifp; 280 struct llinfo_arp *la = NULL; 281 struct sockaddr_dl *sdl; 282 struct rtentry *rt = NULL; 283 struct mbuf *mh; 284 char addr[INET_ADDRSTRLEN]; 285 int error, created = 0; 286 287 if (m->m_flags & M_BCAST) { /* broadcast */ 288 memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr)); 289 return (0); 290 } 291 if (m->m_flags & M_MCAST) { /* multicast */ 292 ETHER_MAP_IP_MULTICAST(&satosin(dst)->sin_addr, desten); 293 return (0); 294 } 295 296 if (rt0 != NULL) { 297 error = rt_checkgate(rt0, &rt); 298 if (error) { 299 m_freem(m); 300 return (error); 301 } 302 303 if ((rt->rt_flags & RTF_LLINFO) == 0) { 304 log(LOG_DEBUG, "%s: %s: route contains no arp" 305 " information\n", __func__, inet_ntop(AF_INET, 306 &satosin(rt_key(rt))->sin_addr, addr, 307 sizeof(addr))); 308 m_freem(m); 309 return (EINVAL); 310 } 311 312 la = (struct llinfo_arp *)rt->rt_llinfo; 313 if (la == NULL) 314 log(LOG_DEBUG, "%s: %s: route without link " 315 "local address\n", __func__, inet_ntop(AF_INET, 316 &satosin(dst)->sin_addr, addr, sizeof(addr))); 317 } else { 318 rt = arplookup(satosin(dst)->sin_addr.s_addr, 1, 0, 319 ifp->if_rdomain); 320 if (rt != NULL) { 321 created = 1; 322 la = ((struct llinfo_arp *)rt->rt_llinfo); 323 } 324 if (la == NULL) 325 log(LOG_DEBUG, "%s: %s: can't allocate llinfo\n", 326 __func__, 327 inet_ntop(AF_INET, &satosin(dst)->sin_addr, 328 addr, sizeof(addr))); 329 } 330 if (la == NULL || rt == NULL) 331 goto bad; 332 sdl = satosdl(rt->rt_gateway); 333 if (sdl->sdl_alen > 0 && sdl->sdl_alen != ETHER_ADDR_LEN) { 334 log(LOG_DEBUG, "%s: %s: incorrect arp information\n", __func__, 335 inet_ntop(AF_INET, &satosin(dst)->sin_addr, 336 addr, sizeof(addr))); 337 goto bad; 338 } 339 /* 340 * Check the address family and length is valid, the address 341 * is resolved; otherwise, try to resolve. 342 */ 343 if ((rt->rt_expire == 0 || rt->rt_expire > time_second) && 344 sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { 345 memcpy(desten, LLADDR(sdl), sdl->sdl_alen); 346 if (created) 347 rtfree(rt); 348 return (0); 349 } 350 if (ifp->if_flags & IFF_NOARP) 351 goto bad; 352 353 /* 354 * There is an arptab entry, but no ethernet address 355 * response yet. Insert mbuf in hold queue if below limit 356 * if above the limit free the queue without queuing the new packet. 357 */ 358 if (la_hold_total < LA_HOLD_TOTAL && la_hold_total < nmbclust / 64) { 359 if (ml_len(&la->la_ml) >= LA_HOLD_QUEUE) { 360 mh = ml_dequeue(&la->la_ml); 361 la_hold_total--; 362 m_freem(mh); 363 } 364 ml_enqueue(&la->la_ml, m); 365 la_hold_total++; 366 } else { 367 la_hold_total -= ml_purge(&la->la_ml); 368 m_freem(m); 369 } 370 371 /* 372 * Re-send the ARP request when appropriate. 373 */ 374 #ifdef DIAGNOSTIC 375 if (rt->rt_expire == 0) { 376 /* This should never happen. (Should it? -gwr) */ 377 printf("%s: unresolved and rt_expire == 0\n", __func__); 378 /* Set expiration time to now (expired). */ 379 rt->rt_expire = time_second; 380 } 381 #endif 382 if (rt->rt_expire) { 383 rt->rt_flags &= ~RTF_REJECT; 384 if (la->la_asked == 0 || rt->rt_expire != time_second) { 385 rt->rt_expire = time_second; 386 if (la->la_asked++ < arp_maxtries) 387 arprequest(ifp, 388 &satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr, 389 &satosin(dst)->sin_addr.s_addr, 390 ac->ac_enaddr); 391 else { 392 rt->rt_flags |= RTF_REJECT; 393 rt->rt_expire += arpt_down; 394 la->la_asked = 0; 395 la_hold_total -= ml_purge(&la->la_ml); 396 } 397 } 398 } 399 if (created) 400 rtfree(rt); 401 return (EAGAIN); 402 403 bad: 404 m_freem(m); 405 if (created) 406 rtfree(rt); 407 return (EINVAL); 408 } 409 410 /* 411 * Common length and type checks are done here, 412 * then the protocol-specific routine is called. 413 */ 414 void 415 arpinput(struct mbuf *m) 416 { 417 struct arphdr *ar; 418 int len; 419 420 #ifdef DIAGNOSTIC 421 if ((m->m_flags & M_PKTHDR) == 0) 422 panic("arpintr"); 423 #endif 424 425 len = sizeof(struct arphdr); 426 if (m->m_len < len && (m = m_pullup(m, len)) == NULL) 427 return; 428 429 ar = mtod(m, struct arphdr *); 430 if (ntohs(ar->ar_hrd) != ARPHRD_ETHER || 431 ntohs(ar->ar_pro) != ETHERTYPE_IP) { 432 m_freem(m); 433 return; 434 } 435 436 len += 2 * (ar->ar_hln + ar->ar_pln); 437 if (m->m_len < len && (m = m_pullup(m, len)) == NULL) 438 return; 439 440 in_arpinput(m); 441 } 442 443 /* 444 * ARP for Internet protocols on Ethernet, RFC 826. 445 * In addition, a sanity check is performed on the sender 446 * protocol address, to catch impersonators. 447 */ 448 void 449 in_arpinput(struct mbuf *m) 450 { 451 struct ether_arp *ea; 452 struct ifnet *ifp; 453 struct ether_header *eh; 454 struct llinfo_arp *la = NULL; 455 struct rtentry *rt = NULL; 456 struct sockaddr_dl *sdl; 457 struct sockaddr sa; 458 struct sockaddr_in sin; 459 struct in_addr isaddr, itaddr; 460 struct mbuf *mh; 461 uint8_t enaddr[ETHER_ADDR_LEN]; 462 char addr[INET_ADDRSTRLEN]; 463 int op, changed = 0, target = 0; 464 unsigned int len, rdomain; 465 466 rdomain = rtable_l2(m->m_pkthdr.ph_rtableid); 467 468 ifp = if_get(m->m_pkthdr.ph_ifidx); 469 if (ifp == NULL) { 470 m_freem(m); 471 return; 472 } 473 ea = mtod(m, struct ether_arp *); 474 op = ntohs(ea->arp_op); 475 if ((op != ARPOP_REQUEST) && (op != ARPOP_REPLY)) 476 goto out; 477 478 memcpy(&itaddr, ea->arp_tpa, sizeof(itaddr)); 479 memcpy(&isaddr, ea->arp_spa, sizeof(isaddr)); 480 memset(&sin, 0, sizeof(sin)); 481 sin.sin_len = sizeof(sin); 482 sin.sin_family = AF_INET; 483 484 if (ETHER_IS_MULTICAST(&ea->arp_sha[0])) { 485 if (!memcmp(ea->arp_sha, etherbroadcastaddr, 486 sizeof (ea->arp_sha))) { 487 inet_ntop(AF_INET, &isaddr, addr, sizeof(addr)); 488 log(LOG_ERR, "arp: ether address is broadcast for " 489 "IP address %s!\n", addr); 490 goto out; 491 } 492 } 493 494 memcpy(enaddr, LLADDR(ifp->if_sadl), ETHER_ADDR_LEN); 495 if (!memcmp(ea->arp_sha, enaddr, sizeof(ea->arp_sha))) 496 goto out; /* it's from me, ignore it. */ 497 498 /* Check target against our interface addresses. */ 499 sin.sin_addr = itaddr; 500 rt = rtalloc(sintosa(&sin), 0, rdomain); 501 if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && 502 rt->rt_ifidx == ifp->if_index) 503 target = 1; 504 rtfree(rt); 505 rt = NULL; 506 507 #if NCARP > 0 508 if (target && op == ARPOP_REQUEST && ifp->if_type == IFT_CARP && 509 !carp_iamatch(ifp, enaddr)) 510 goto out; 511 #endif 512 513 /* Do we have an ARP cache for the sender? Create if we are target. */ 514 rt = arplookup(isaddr.s_addr, target, 0, rdomain); 515 516 /* Check sender against our interface addresses. */ 517 if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && 518 rt->rt_ifidx == ifp->if_index && isaddr.s_addr != INADDR_ANY) { 519 inet_ntop(AF_INET, &isaddr, addr, sizeof(addr)); 520 log(LOG_ERR, 521 "duplicate IP address %s sent from ethernet address %s\n", 522 addr, ether_sprintf(ea->arp_sha)); 523 itaddr = isaddr; 524 } else if (rt != NULL && (sdl = satosdl(rt->rt_gateway)) != NULL) { 525 la = (struct llinfo_arp *)rt->rt_llinfo; 526 if (sdl->sdl_alen) { 527 if (memcmp(ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) { 528 if (rt->rt_flags & 529 (RTF_PERMANENT_ARP|RTF_LOCAL)) { 530 inet_ntop(AF_INET, &isaddr, addr, 531 sizeof(addr)); 532 log(LOG_WARNING, "arp: attempt to" 533 " overwrite permanent entry for %s" 534 " by %s on %s\n", addr, 535 ether_sprintf(ea->arp_sha), 536 ifp->if_xname); 537 goto out; 538 } else if (rt->rt_ifidx != ifp->if_index) { 539 #if NCARP > 0 540 if (ifp->if_type != IFT_CARP) 541 #endif 542 { 543 struct ifnet *rifp = if_get( 544 rt->rt_ifidx); 545 if (rifp == NULL) 546 goto out; 547 inet_ntop(AF_INET, &isaddr, 548 addr, sizeof(addr)); 549 log(LOG_WARNING, "arp: attempt" 550 " to overwrite entry for" 551 " %s on %s by %s on %s\n", 552 addr, rifp->if_xname, 553 ether_sprintf(ea->arp_sha), 554 ifp->if_xname); 555 if_put(rifp); 556 } 557 goto out; 558 } else { 559 inet_ntop(AF_INET, &isaddr, addr, 560 sizeof(addr)); 561 log(LOG_INFO, "arp info overwritten for" 562 " %s by %s on %s\n", addr, 563 ether_sprintf(ea->arp_sha), 564 ifp->if_xname); 565 rt->rt_expire = 1;/* no longer static */ 566 } 567 changed = 1; 568 } 569 } else if (!if_isconnected(ifp, rt->rt_ifidx)) { 570 struct ifnet *rifp = if_get(rt->rt_ifidx); 571 if (rifp == NULL) 572 goto out; 573 inet_ntop(AF_INET, &isaddr, addr, sizeof(addr)); 574 log(LOG_WARNING, 575 "arp: attempt to add entry for %s " 576 "on %s by %s on %s\n", addr, 577 rifp->if_xname, 578 ether_sprintf(ea->arp_sha), 579 ifp->if_xname); 580 if_put(rifp); 581 goto out; 582 } 583 sdl->sdl_alen = sizeof(ea->arp_sha); 584 memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha)); 585 if (rt->rt_expire) 586 rt->rt_expire = time_second + arpt_keep; 587 rt->rt_flags &= ~RTF_REJECT; 588 /* Notify userland that an ARP resolution has been done. */ 589 if (la->la_asked || changed) { 590 KERNEL_LOCK(); 591 rt_sendmsg(rt, RTM_RESOLVE, ifp->if_rdomain); 592 KERNEL_UNLOCK(); 593 } 594 la->la_asked = 0; 595 while ((len = ml_len(&la->la_ml)) != 0) { 596 mh = ml_dequeue(&la->la_ml); 597 la_hold_total--; 598 599 ifp->if_output(ifp, mh, rt_key(rt), rt); 600 601 if (ml_len(&la->la_ml) == len) { 602 /* mbuf is back in queue. Discard. */ 603 while ((mh = ml_dequeue(&la->la_ml)) != NULL) { 604 la_hold_total--; 605 m_freem(mh); 606 } 607 break; 608 } 609 } 610 } 611 612 if (op != ARPOP_REQUEST) { 613 out: 614 rtfree(rt); 615 if_put(ifp); 616 m_freem(m); 617 return; 618 } 619 620 rtfree(rt); 621 if (target) { 622 /* We are the target and already have all info for the reply */ 623 memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha)); 624 memcpy(ea->arp_sha, LLADDR(ifp->if_sadl), sizeof(ea->arp_sha)); 625 } else { 626 rt = arplookup(itaddr.s_addr, 0, SIN_PROXY, rdomain); 627 if (rt == NULL) 628 goto out; 629 /* protect from possible duplicates only owner should respond */ 630 if (rt->rt_ifidx != ifp->if_index) 631 goto out; 632 memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha)); 633 sdl = satosdl(rt->rt_gateway); 634 memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha)); 635 rtfree(rt); 636 } 637 638 memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa)); 639 memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa)); 640 ea->arp_op = htons(ARPOP_REPLY); 641 ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 642 eh = (struct ether_header *)sa.sa_data; 643 memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost)); 644 memcpy(eh->ether_shost, enaddr, sizeof(eh->ether_shost)); 645 646 eh->ether_type = htons(ETHERTYPE_ARP); 647 sa.sa_family = pseudo_AF_HDRCMPLT; 648 sa.sa_len = sizeof(sa); 649 ifp->if_output(ifp, m, &sa, NULL); 650 if_put(ifp); 651 } 652 653 /* 654 * Free an arp entry. 655 */ 656 void 657 arptfree(struct rtentry *rt) 658 { 659 struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; 660 struct sockaddr_dl *sdl = satosdl(rt->rt_gateway); 661 struct ifnet *ifp; 662 663 ifp = if_get(rt->rt_ifidx); 664 if ((sdl != NULL) && (sdl->sdl_family == AF_LINK)) { 665 sdl->sdl_alen = 0; 666 la->la_asked = 0; 667 } 668 669 if (!ISSET(rt->rt_flags, RTF_STATIC)) 670 rtdeletemsg(rt, ifp, ifp->if_rdomain); 671 if_put(ifp); 672 } 673 674 /* 675 * Lookup or enter a new address in arptab. 676 */ 677 struct rtentry * 678 arplookup(u_int32_t addr, int create, int proxy, u_int tableid) 679 { 680 struct rtentry *rt; 681 struct sockaddr_inarp sin; 682 int flags; 683 684 memset(&sin, 0, sizeof(sin)); 685 sin.sin_len = sizeof(sin); 686 sin.sin_family = AF_INET; 687 sin.sin_addr.s_addr = addr; 688 sin.sin_other = proxy ? SIN_PROXY : 0; 689 flags = (create) ? RT_RESOLVE : 0; 690 691 rt = rtalloc((struct sockaddr *)&sin, flags, tableid); 692 if (!rtisvalid(rt) || ISSET(rt->rt_flags, RTF_GATEWAY) || 693 !ISSET(rt->rt_flags, RTF_LLINFO) || 694 rt->rt_gateway->sa_family != AF_LINK) { 695 rtfree(rt); 696 return (NULL); 697 } 698 699 if (proxy && !ISSET(rt->rt_flags, RTF_ANNOUNCE)) { 700 struct rtentry *mrt = NULL; 701 #if defined(ART) && !defined(SMALL_KERNEL) 702 mrt = rt; 703 KERNEL_LOCK(); 704 while ((mrt = rtable_mpath_next(mrt)) != NULL) { 705 if (ISSET(mrt->rt_flags, RTF_ANNOUNCE)) { 706 rtref(mrt); 707 break; 708 } 709 } 710 KERNEL_UNLOCK(); 711 #endif /* ART && !SMALL_KERNEL */ 712 rtfree(rt); 713 return (mrt); 714 } 715 716 return (rt); 717 } 718 719 /* 720 * Check whether we do proxy ARP for this address and we point to ourselves. 721 */ 722 int 723 arpproxy(struct in_addr in, unsigned int rtableid) 724 { 725 struct sockaddr_dl *sdl; 726 struct rtentry *rt; 727 struct ifnet *ifp; 728 int found = 0; 729 730 rt = arplookup(in.s_addr, 0, SIN_PROXY, rtableid); 731 if (!rtisvalid(rt)) { 732 rtfree(rt); 733 return (0); 734 } 735 736 /* Check that arp information are correct. */ 737 sdl = satosdl(rt->rt_gateway); 738 if (sdl->sdl_alen != ETHER_ADDR_LEN) { 739 rtfree(rt); 740 return (0); 741 } 742 743 ifp = if_get(rt->rt_ifidx); 744 if (ifp == NULL) { 745 rtfree(rt); 746 return (0); 747 } 748 749 if (!memcmp(LLADDR(sdl), LLADDR(ifp->if_sadl), sdl->sdl_alen)) 750 found = 1; 751 752 if_put(ifp); 753 rtfree(rt); 754 return (found); 755 } 756 757 /* 758 * Called from Ethernet interrupt handlers 759 * when ether packet type ETHERTYPE_REVARP 760 * is received. Common length and type checks are done here, 761 * then the protocol-specific routine is called. 762 */ 763 void 764 revarpinput(struct mbuf *m) 765 { 766 struct arphdr *ar; 767 768 if (m->m_len < sizeof(struct arphdr)) 769 goto out; 770 ar = mtod(m, struct arphdr *); 771 if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) 772 goto out; 773 if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) 774 goto out; 775 switch (ntohs(ar->ar_pro)) { 776 777 case ETHERTYPE_IP: 778 in_revarpinput(m); 779 return; 780 781 default: 782 break; 783 } 784 out: 785 m_freem(m); 786 } 787 788 /* 789 * RARP for Internet protocols on Ethernet. 790 * Algorithm is that given in RFC 903. 791 * We are only using for bootstrap purposes to get an ip address for one of 792 * our interfaces. Thus we support no user-interface. 793 * 794 * Since the contents of the RARP reply are specific to the interface that 795 * sent the request, this code must ensure that they are properly associated. 796 * 797 * Note: also supports ARP via RARP packets, per the RFC. 798 */ 799 void 800 in_revarpinput(struct mbuf *m) 801 { 802 struct ifnet *ifp = NULL; 803 struct ether_arp *ar; 804 int op; 805 806 ar = mtod(m, struct ether_arp *); 807 op = ntohs(ar->arp_op); 808 switch (op) { 809 case ARPOP_REQUEST: 810 case ARPOP_REPLY: /* per RFC */ 811 in_arpinput(m); 812 return; 813 case ARPOP_REVREPLY: 814 break; 815 case ARPOP_REVREQUEST: /* handled by rarpd(8) */ 816 default: 817 goto out; 818 } 819 #ifdef NFSCLIENT 820 if (revarp_ifidx == 0) 821 goto out; 822 if (revarp_ifidx != m->m_pkthdr.ph_ifidx) /* !same interface */ 823 goto out; 824 if (revarp_finished) 825 goto wake; 826 ifp = if_get(revarp_ifidx); 827 if (ifp == NULL) 828 goto out; 829 if (memcmp(ar->arp_tha, LLADDR(ifp->if_sadl), sizeof(ar->arp_tha))) 830 goto out; 831 memcpy(&revarp_srvip, ar->arp_spa, sizeof(revarp_srvip)); 832 memcpy(&revarp_myip, ar->arp_tpa, sizeof(revarp_myip)); 833 revarp_finished = 1; 834 wake: /* Do wakeup every time in case it was missed. */ 835 wakeup((caddr_t)&revarp_myip); 836 #endif 837 838 out: 839 m_freem(m); 840 if_put(ifp); 841 } 842 843 /* 844 * Send a RARP request for the ip address of the specified interface. 845 * The request should be RFC 903-compliant. 846 */ 847 void 848 revarprequest(struct ifnet *ifp) 849 { 850 struct sockaddr sa; 851 struct mbuf *m; 852 struct ether_header *eh; 853 struct ether_arp *ea; 854 struct arpcom *ac = (struct arpcom *)ifp; 855 856 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) 857 return; 858 m->m_len = sizeof(*ea); 859 m->m_pkthdr.len = sizeof(*ea); 860 MH_ALIGN(m, sizeof(*ea)); 861 ea = mtod(m, struct ether_arp *); 862 eh = (struct ether_header *)sa.sa_data; 863 memset(ea, 0, sizeof(*ea)); 864 memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost)); 865 eh->ether_type = htons(ETHERTYPE_REVARP); 866 ea->arp_hrd = htons(ARPHRD_ETHER); 867 ea->arp_pro = htons(ETHERTYPE_IP); 868 ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ 869 ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ 870 ea->arp_op = htons(ARPOP_REVREQUEST); 871 memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(ea->arp_tha)); 872 memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha)); 873 memcpy(ea->arp_tha, ac->ac_enaddr, sizeof(ea->arp_tha)); 874 sa.sa_family = pseudo_AF_HDRCMPLT; 875 sa.sa_len = sizeof(sa); 876 m->m_flags |= M_BCAST; 877 ifp->if_output(ifp, m, &sa, NULL); 878 } 879 880 #ifdef NFSCLIENT 881 /* 882 * RARP for the ip address of the specified interface, but also 883 * save the ip address of the server that sent the answer. 884 * Timeout if no response is received. 885 */ 886 int 887 revarpwhoarewe(struct ifnet *ifp, struct in_addr *serv_in, 888 struct in_addr *clnt_in) 889 { 890 int result, count = 20; 891 892 if (revarp_finished) 893 return EIO; 894 895 revarp_ifidx = ifp->if_index; 896 while (count--) { 897 revarprequest(ifp); 898 result = tsleep((caddr_t)&revarp_myip, PSOCK, "revarp", hz/2); 899 if (result != EWOULDBLOCK) 900 break; 901 } 902 revarp_ifidx = 0; 903 if (!revarp_finished) 904 return ENETUNREACH; 905 906 memcpy(serv_in, &revarp_srvip, sizeof(*serv_in)); 907 memcpy(clnt_in, &revarp_myip, sizeof(*clnt_in)); 908 return 0; 909 } 910 911 /* For compatibility: only saves interface address. */ 912 int 913 revarpwhoami(struct in_addr *in, struct ifnet *ifp) 914 { 915 struct in_addr server; 916 return (revarpwhoarewe(ifp, &server, in)); 917 } 918 #endif /* NFSCLIENT */ 919