1 /* 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)if_ether.c 8.1 (Berkeley) 6/10/93 34 * $Id: if_arp.c,v 1.12 1994/05/13 06:05:55 mycroft Exp $ 35 */ 36 37 /* 38 * Ethernet address resolution protocol. 39 * TODO: 40 * add "inuse/lock" bit (or ref. count) along with valid bit 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/malloc.h> 46 #include <sys/mbuf.h> 47 #include <sys/socket.h> 48 #include <sys/time.h> 49 #include <sys/kernel.h> 50 #include <sys/errno.h> 51 #include <sys/ioctl.h> 52 #include <sys/syslog.h> 53 54 #include <net/if.h> 55 #include <net/if_dl.h> 56 #include <net/route.h> 57 58 #include <netinet/in.h> 59 #include <netinet/in_systm.h> 60 #include <netinet/in_var.h> 61 #include <netinet/ip.h> 62 #include <netinet/if_ether.h> 63 64 #define SIN(s) ((struct sockaddr_in *)s) 65 #define SDL(s) ((struct sockaddr_dl *)s) 66 #define SRP(s) ((struct sockaddr_inarp *)s) 67 68 /* 69 * ARP trailer negotiation. Trailer protocol is not IP specific, 70 * but ARP request/response use IP addresses. 71 */ 72 #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL 73 74 /* timer values */ 75 int arpt_prune = (5*60*1); /* walk list every 5 minutes */ 76 int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ 77 int arpt_down = 20; /* once declared down, don't send for 20 secs */ 78 #define rt_expire rt_rmx.rmx_expire 79 80 static void arprequest __P((struct arpcom *, u_long *, u_long *, u_char *)); 81 static void arptfree __P((struct llinfo_arp *)); 82 static void arptimer __P((void *)); 83 static struct llinfo_arp *arplookup __P((u_long, int, int)); 84 static void in_arpinput __P((struct mbuf *)); 85 86 extern struct ifnet loif; 87 extern struct timeval time; 88 struct llinfo_arp llinfo_arp = {&llinfo_arp, &llinfo_arp}; 89 struct ifqueue arpintrq = {0, 0, 0, 50}; 90 int arp_inuse, arp_allocated, arp_intimer; 91 int arp_maxtries = 5; 92 int useloopback = 1; /* use loopback interface for local traffic */ 93 int arpinit_done = 0; 94 95 /* revarp state */ 96 struct in_addr myip; 97 int myip_initialized = 0; 98 int revarp_in_progress = 0; 99 struct ifnet *myip_ifp = NULL; 100 101 /* 102 * Timeout routine. Age arp_tab entries periodically. 103 */ 104 /* ARGSUSED */ 105 static void 106 arptimer(arg) 107 void *arg; 108 { 109 int s = splnet(); 110 register struct llinfo_arp *la = llinfo_arp.la_next; 111 112 timeout(arptimer, NULL, arpt_prune * hz); 113 while (la != &llinfo_arp) { 114 register struct rtentry *rt = la->la_rt; 115 la = la->la_next; 116 if (rt->rt_expire && rt->rt_expire <= time.tv_sec) 117 arptfree(la->la_prev); /* timer has expired; clear */ 118 } 119 splx(s); 120 } 121 122 /* 123 * Parallel to llc_rtrequest. 124 */ 125 void 126 arp_rtrequest(req, rt, sa) 127 int req; 128 register struct rtentry *rt; 129 struct sockaddr *sa; 130 { 131 register struct sockaddr *gate = rt->rt_gateway; 132 register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; 133 static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; 134 135 if (!arpinit_done) { 136 arpinit_done = 1; 137 timeout(arptimer, (caddr_t)0, hz); 138 } 139 if (rt->rt_flags & RTF_GATEWAY) 140 return; 141 switch (req) { 142 143 case RTM_ADD: 144 /* 145 * XXX: If this is a manually added route to interface 146 * such as older version of routed or gated might provide, 147 * restore cloning bit. 148 */ 149 if ((rt->rt_flags & RTF_HOST) == 0 && 150 SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) 151 rt->rt_flags |= RTF_CLONING; 152 if (rt->rt_flags & RTF_CLONING) { 153 /* 154 * Case 1: This route should come from a route to iface. 155 */ 156 rt_setgate(rt, rt_key(rt), 157 (struct sockaddr *)&null_sdl); 158 gate = rt->rt_gateway; 159 SDL(gate)->sdl_type = rt->rt_ifp->if_type; 160 SDL(gate)->sdl_index = rt->rt_ifp->if_index; 161 rt->rt_expire = time.tv_sec; 162 break; 163 } 164 /* Announce a new entry if requested. */ 165 if (rt->rt_flags & RTF_ANNOUNCE) 166 arprequest((struct arpcom *)rt->rt_ifp, 167 &SIN(rt_key(rt))->sin_addr.s_addr, 168 &SIN(rt_key(rt))->sin_addr.s_addr, 169 (u_char *)LLADDR(SDL(gate))); 170 /*FALLTHROUGH*/ 171 case RTM_RESOLVE: 172 if (gate->sa_family != AF_LINK || 173 gate->sa_len < sizeof(null_sdl)) { 174 log(LOG_DEBUG, "arp_rtrequest: bad gateway value"); 175 break; 176 } 177 SDL(gate)->sdl_type = rt->rt_ifp->if_type; 178 SDL(gate)->sdl_index = rt->rt_ifp->if_index; 179 if (la != 0) 180 break; /* This happens on a route change */ 181 /* 182 * Case 2: This route may come from cloning, or a manual route 183 * add with a LL address. 184 */ 185 R_Malloc(la, struct llinfo_arp *, sizeof(*la)); 186 rt->rt_llinfo = (caddr_t)la; 187 if (la == 0) { 188 log(LOG_DEBUG, "arp_rtrequest: malloc failed\n"); 189 break; 190 } 191 arp_inuse++, arp_allocated++; 192 Bzero(la, sizeof(*la)); 193 la->la_rt = rt; 194 rt->rt_flags |= RTF_LLINFO; 195 insque(la, &llinfo_arp); 196 if (SIN(rt_key(rt))->sin_addr.s_addr == 197 (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { 198 /* 199 * This test used to be 200 * if (loif.if_flags & IFF_UP) 201 * It allowed local traffic to be forced 202 * through the hardware by configuring the loopback down. 203 * However, it causes problems during network configuration 204 * for boards that can't receive packets they send. 205 * It is now necessary to clear "useloopback" and remove 206 * the route to force traffic out to the hardware. 207 */ 208 rt->rt_expire = 0; 209 Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr, 210 LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); 211 if (useloopback) 212 rt->rt_ifp = &loif; 213 214 } 215 break; 216 217 case RTM_DELETE: 218 if (la == 0) 219 break; 220 arp_inuse--; 221 remque(la); 222 rt->rt_llinfo = 0; 223 rt->rt_flags &= ~RTF_LLINFO; 224 if (la->la_hold) 225 m_freem(la->la_hold); 226 Free((caddr_t)la); 227 } 228 } 229 230 /* 231 * Broadcast an ARP packet, asking who has addr on interface ac. 232 */ 233 void 234 arpwhohas(ac, addr) 235 register struct arpcom *ac; 236 register struct in_addr *addr; 237 { 238 arprequest(ac, &ac->ac_ipaddr.s_addr, &addr->s_addr, ac->ac_enaddr); 239 } 240 241 /* 242 * Broadcast an ARP request. Caller specifies: 243 * - arp header source ip address 244 * - arp header target ip address 245 * - arp header source ethernet address 246 */ 247 static void 248 arprequest(ac, sip, tip, enaddr) 249 register struct arpcom *ac; 250 register u_long *sip, *tip; 251 register u_char *enaddr; 252 { 253 register struct mbuf *m; 254 register struct ether_header *eh; 255 register struct ether_arp *ea; 256 struct sockaddr sa; 257 258 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) 259 return; 260 m->m_len = sizeof(*ea); 261 m->m_pkthdr.len = sizeof(*ea); 262 MH_ALIGN(m, sizeof(*ea)); 263 ea = mtod(m, struct ether_arp *); 264 eh = (struct ether_header *)sa.sa_data; 265 bzero((caddr_t)ea, sizeof (*ea)); 266 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 267 sizeof(eh->ether_dhost)); 268 eh->ether_type = htons(ETHERTYPE_ARP); 269 ea->arp_hrd = htons(ARPHRD_ETHER); 270 ea->arp_pro = htons(ETHERTYPE_IP); 271 ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ 272 ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ 273 ea->arp_op = htons(ARPOP_REQUEST); 274 bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); 275 bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); 276 bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa)); 277 sa.sa_family = AF_UNSPEC; 278 sa.sa_len = sizeof(sa); 279 (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); 280 } 281 282 /* 283 * Resolve an IP address into an ethernet address. If success, 284 * desten is filled in. If there is no entry in arptab, 285 * set one up and broadcast a request for the IP address. 286 * Hold onto this mbuf and resend it once the address 287 * is finally resolved. A return value of 1 indicates 288 * that desten has been filled in and the packet should be sent 289 * normally; a 0 return indicates that the packet has been 290 * taken over here, either now or for later transmission. 291 */ 292 int 293 arpresolve(ac, rt, m, dst, desten) 294 register struct arpcom *ac; 295 register struct rtentry *rt; 296 struct mbuf *m; 297 register struct sockaddr *dst; 298 register u_char *desten; 299 { 300 register struct llinfo_arp *la; 301 struct sockaddr_dl *sdl; 302 303 if (m->m_flags & M_BCAST) { /* broadcast */ 304 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten, 305 sizeof(etherbroadcastaddr)); 306 return (1); 307 } 308 if (m->m_flags & M_MCAST) { /* multicast */ 309 ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); 310 return(1); 311 } 312 if (rt) 313 la = (struct llinfo_arp *)rt->rt_llinfo; 314 else { 315 if (la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)) 316 rt = la->la_rt; 317 } 318 if (la == 0 || rt == 0) { 319 log(LOG_DEBUG, "arpresolve: can't allocate llinfo"); 320 m_freem(m); 321 return (0); 322 } 323 sdl = SDL(rt->rt_gateway); 324 /* 325 * Check the address family and length is valid, the address 326 * is resolved; otherwise, try to resolve. 327 */ 328 if ((rt->rt_expire == 0 || rt->rt_expire > time.tv_sec) && 329 sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { 330 bcopy(LLADDR(sdl), desten, sdl->sdl_alen); 331 return 1; 332 } 333 /* 334 * There is an arptab entry, but no ethernet address 335 * response yet. Replace the held mbuf with this 336 * latest one. 337 */ 338 if (la->la_hold) 339 m_freem(la->la_hold); 340 la->la_hold = m; 341 if (rt->rt_expire) { 342 rt->rt_flags &= ~RTF_REJECT; 343 if (la->la_asked == 0 || rt->rt_expire != time.tv_sec) { 344 rt->rt_expire = time.tv_sec; 345 if (la->la_asked++ < arp_maxtries) 346 arpwhohas(ac, &(SIN(dst)->sin_addr)); 347 else { 348 rt->rt_flags |= RTF_REJECT; 349 rt->rt_expire += arpt_down; 350 la->la_asked = 0; 351 } 352 } 353 } 354 return (0); 355 } 356 357 /* 358 * Common length and type checks are done here, 359 * then the protocol-specific routine is called. 360 */ 361 void 362 arpintr() 363 { 364 register struct mbuf *m; 365 register struct arphdr *ar; 366 int s; 367 368 while (arpintrq.ifq_head) { 369 s = splimp(); 370 IF_DEQUEUE(&arpintrq, m); 371 splx(s); 372 if (m == 0 || (m->m_flags & M_PKTHDR) == 0) 373 panic("arpintr"); 374 if (m->m_len >= sizeof(struct arphdr) && 375 (ar = mtod(m, struct arphdr *)) && 376 ntohs(ar->ar_hrd) == ARPHRD_ETHER && 377 m->m_len >= 378 sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) 379 switch (ntohs(ar->ar_pro)) { 380 381 case ETHERTYPE_IP: 382 case ETHERTYPE_IPTRAILERS: 383 in_arpinput(m); 384 continue; 385 } 386 m_freem(m); 387 } 388 } 389 390 /* 391 * ARP for Internet protocols on 10 Mb/s Ethernet. 392 * Algorithm is that given in RFC 826. 393 * In addition, a sanity check is performed on the sender 394 * protocol address, to catch impersonators. 395 * We no longer handle negotiations for use of trailer protocol: 396 * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent 397 * along with IP replies if we wanted trailers sent to us, 398 * and also sent them in response to IP replies. 399 * This allowed either end to announce the desire to receive 400 * trailer packets. 401 * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, 402 * but formerly didn't normally send requests. 403 */ 404 static void 405 in_arpinput(m) 406 struct mbuf *m; 407 { 408 register struct ether_arp *ea; 409 register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif; 410 struct ether_header *eh; 411 register struct llinfo_arp *la = 0; 412 register struct rtentry *rt; 413 struct in_ifaddr *ia, *maybe_ia = 0; 414 struct sockaddr_dl *sdl; 415 struct sockaddr sa; 416 struct in_addr isaddr, itaddr, myaddr; 417 int op; 418 419 ea = mtod(m, struct ether_arp *); 420 op = ntohs(ea->arp_op); 421 bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr)); 422 bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr)); 423 for (ia = in_ifaddr; ia; ia = ia->ia_next) 424 if (ia->ia_ifp == &ac->ac_if) { 425 maybe_ia = ia; 426 if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) || 427 (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)) 428 break; 429 } 430 if (maybe_ia == 0) 431 goto out; 432 myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr; 433 if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr, 434 sizeof (ea->arp_sha))) 435 goto out; /* it's from me, ignore it. */ 436 if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr, 437 sizeof (ea->arp_sha))) { 438 log(LOG_ERR, 439 "arp: ether address is broadcast for IP address %x!\n", 440 ntohl(isaddr.s_addr)); 441 goto out; 442 } 443 if (isaddr.s_addr == myaddr.s_addr) { 444 log(LOG_ERR, 445 "duplicate IP address %x!! sent from ethernet address: %s\n", 446 ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha)); 447 itaddr = myaddr; 448 goto reply; 449 } 450 la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0); 451 if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) { 452 if (sdl->sdl_alen && 453 bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) 454 log(LOG_INFO, "arp info overwritten for %x by %s\n", 455 isaddr.s_addr, ether_sprintf(ea->arp_sha)); 456 bcopy((caddr_t)ea->arp_sha, LLADDR(sdl), 457 sdl->sdl_alen = sizeof(ea->arp_sha)); 458 if (rt->rt_expire) 459 rt->rt_expire = time.tv_sec + arpt_keep; 460 rt->rt_flags &= ~RTF_REJECT; 461 la->la_asked = 0; 462 if (la->la_hold) { 463 (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold, 464 rt_key(rt), rt); 465 la->la_hold = 0; 466 } 467 } 468 reply: 469 if (op != ARPOP_REQUEST) { 470 out: 471 m_freem(m); 472 return; 473 } 474 if (itaddr.s_addr == myaddr.s_addr) { 475 /* I am the target */ 476 bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, 477 sizeof(ea->arp_sha)); 478 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, 479 sizeof(ea->arp_sha)); 480 } else { 481 la = arplookup(itaddr.s_addr, 0, SIN_PROXY); 482 if (la == 0) 483 goto out; 484 rt = la->la_rt; 485 bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, 486 sizeof(ea->arp_sha)); 487 sdl = SDL(rt->rt_gateway); 488 bcopy(LLADDR(sdl), (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); 489 } 490 491 bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa)); 492 bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); 493 ea->arp_op = htons(ARPOP_REPLY); 494 ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 495 eh = (struct ether_header *)sa.sa_data; 496 bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost, 497 sizeof(eh->ether_dhost)); 498 eh->ether_type = htons(ETHERTYPE_ARP); 499 sa.sa_family = AF_UNSPEC; 500 sa.sa_len = sizeof(sa); 501 (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); 502 return; 503 } 504 505 /* 506 * Free an arp entry. 507 */ 508 static void 509 arptfree(la) 510 register struct llinfo_arp *la; 511 { 512 register struct rtentry *rt = la->la_rt; 513 register struct sockaddr_dl *sdl; 514 515 if (rt == 0) 516 panic("arptfree"); 517 if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) && 518 sdl->sdl_family == AF_LINK) { 519 sdl->sdl_alen = 0; 520 la->la_asked = 0; 521 rt->rt_flags &= ~RTF_REJECT; 522 return; 523 } 524 rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt), 525 0, (struct rtentry **)0); 526 } 527 528 /* 529 * Lookup or enter a new address in arptab. 530 */ 531 static struct llinfo_arp * 532 arplookup(addr, create, proxy) 533 u_long addr; 534 int create, proxy; 535 { 536 register struct rtentry *rt; 537 static struct sockaddr_inarp sin; 538 539 sin.sin_len = sizeof(sin); 540 sin.sin_family = AF_INET; 541 sin.sin_addr.s_addr = addr; 542 sin.sin_other = proxy ? SIN_PROXY : 0; 543 rt = rtalloc1((struct sockaddr *)&sin, create); 544 if (rt == 0) 545 return (0); 546 rt->rt_refcnt--; 547 if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || 548 rt->rt_gateway->sa_family != AF_LINK) { 549 if (create) 550 log(LOG_DEBUG, "arptnew failed on %x\n", ntohl(addr)); 551 return (0); 552 } 553 return ((struct llinfo_arp *)rt->rt_llinfo); 554 } 555 556 int 557 arpioctl(cmd, data) 558 int cmd; 559 caddr_t data; 560 { 561 return (EOPNOTSUPP); 562 } 563 564 /* 565 * Called from 10 Mb/s Ethernet interrupt handlers 566 * when ether packet type ETHERTYPE_REVARP 567 * is received. Common length and type checks are done here, 568 * then the protocol-specific routine is called. 569 */ 570 void 571 revarpinput(m) 572 struct mbuf *m; 573 { 574 struct arphdr *ar; 575 int op, s; 576 577 if (m->m_len < sizeof(struct arphdr)) 578 goto out; 579 ar = mtod(m, struct arphdr *); 580 if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) 581 goto out; 582 if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) 583 goto out; 584 switch (ntohs(ar->ar_pro)) { 585 586 case ETHERTYPE_IP: 587 case ETHERTYPE_IPTRAILERS: 588 in_revarpinput(m); 589 return; 590 591 default: 592 break; 593 } 594 out: 595 m_freem(m); 596 } 597 598 /* 599 * RARP for Internet protocols on 10 Mb/s Ethernet. 600 * Algorithm is that given in RFC 903. 601 * We are only using for bootstrap purposes to get an ip address for one of 602 * our interfaces. Thus we support no user-interface. 603 * 604 * Since the contents of the RARP reply are specific to the interface that 605 * sent the request, this code must ensure that they are properly associated. 606 * 607 * Note: also supports ARP via RARP packets, per the RFC. 608 */ 609 in_revarpinput(m) 610 struct mbuf *m; 611 { 612 struct ifnet *ifp; 613 struct ether_arp *ar; 614 int op, s; 615 616 ar = mtod(m, struct ether_arp *); 617 op = ntohs(ar->arp_op); 618 switch (op) { 619 case ARPOP_REQUEST: 620 case ARPOP_REPLY: /* per RFC */ 621 in_arpinput(m); 622 return; 623 case ARPOP_REVREPLY: 624 break; 625 case ARPOP_REVREQUEST: /* handled by rarpd(8) */ 626 default: 627 goto out; 628 } 629 if (!revarp_in_progress) 630 goto out; 631 ifp = m->m_pkthdr.rcvif; 632 if (ifp != myip_ifp) /* !same interface */ 633 goto out; 634 if (myip_initialized != 0) 635 goto out; 636 if (bcmp(ar->arp_tha, ((struct arpcom *)ifp)->ac_enaddr, 637 sizeof(ar->arp_tha))) 638 goto out; 639 bcopy((caddr_t)ar->arp_tpa, (caddr_t)&myip, sizeof(myip)); 640 myip_initialized = 1; 641 wakeup((caddr_t)&myip); 642 643 out: 644 m_freem(m); 645 } 646 647 /* 648 * Send a RARP request for the ip address of the specified interface. 649 * The request should be RFC 903-compliant. 650 */ 651 void 652 revarprequest(ifp) 653 struct ifnet *ifp; 654 { 655 struct sockaddr sa; 656 struct mbuf *m; 657 struct ether_header *eh; 658 struct ether_arp *ea; 659 struct arpcom *ac = (struct arpcom *)ifp; 660 661 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) 662 return; 663 m->m_len = sizeof(*ea); 664 m->m_pkthdr.len = sizeof(*ea); 665 MH_ALIGN(m, sizeof(*ea)); 666 ea = mtod(m, struct ether_arp *); 667 eh = (struct ether_header *)sa.sa_data; 668 bzero((caddr_t)ea, sizeof(*ea)); 669 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, 670 sizeof(eh->ether_dhost)); 671 eh->ether_type = htons(ETHERTYPE_REVARP); 672 ea->arp_hrd = htons(ARPHRD_ETHER); 673 ea->arp_pro = htons(ETHERTYPE_IP); 674 ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ 675 ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ 676 ea->arp_op = htons(ARPOP_REVREQUEST); 677 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, 678 sizeof(ea->arp_sha)); 679 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_tha, 680 sizeof(ea->arp_tha)); 681 sa.sa_family = AF_UNSPEC; 682 sa.sa_len = sizeof(sa); 683 ifp->if_output(ifp, m, &sa, (struct rtentry *)0); 684 } 685 686 /* 687 * RARP for the ip address of the specified interface. Timeout if 688 * no response is received. 689 */ 690 int 691 revarpwhoami(in, ifp) 692 struct in_addr *in; 693 struct ifnet *ifp; 694 { 695 int result, count = 20; 696 697 if (myip_initialized) 698 return EIO; 699 700 myip_ifp = ifp; 701 revarp_in_progress = 1; 702 while (count--) { 703 revarprequest(ifp); 704 result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2); 705 if (result != EWOULDBLOCK) 706 break; 707 } 708 revarp_in_progress = 0; 709 if (!myip_initialized) 710 return ENETUNREACH; 711 712 bcopy((caddr_t)&myip, in, sizeof(*in)); 713 return 0; 714 } 715