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