|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1986, 1988, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 ! 59: */ ! 60: ! 61: /* ! 62: * Ethernet address resolution protocol. ! 63: * TODO: ! 64: * add "inuse/lock" bit (or ref. count) along with valid bit ! 65: */ ! 66: ! 67: ! 68: #include <sys/param.h> ! 69: #include <sys/systm.h> ! 70: #include <sys/malloc.h> ! 71: #include <sys/mbuf.h> ! 72: #include <sys/socket.h> ! 73: #include <sys/time.h> ! 74: #include <sys/kernel.h> ! 75: #include <sys/errno.h> ! 76: #include <sys/ioctl.h> ! 77: #include <sys/syslog.h> ! 78: ! 79: #include <net/if.h> ! 80: #include <net/if_dl.h> ! 81: #include <net/route.h> ! 82: ! 83: #include <netinet/in.h> ! 84: #include <netinet/in_systm.h> ! 85: #include <netinet/in_var.h> ! 86: #include <netinet/ip.h> ! 87: #include <netinet/if_ether.h> ! 88: ! 89: #if INET ! 90: ! 91: struct ifqueue arpintrq; ! 92: ! 93: struct llinfo_arp llinfo_arp; /* head of the llinfo queue */ ! 94: ! 95: #define SIN(s) ((struct sockaddr_in *)s) ! 96: #define SDL(s) ((struct sockaddr_dl *)s) ! 97: #define SRP(s) ((struct sockaddr_inarp *)s) ! 98: ! 99: /* ! 100: * ARP trailer negotiation. Trailer protocol is not IP specific, ! 101: * but ARP request/response use IP addresses. ! 102: */ ! 103: #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL ! 104: ! 105: /* timer values */ ! 106: int arpt_prune = (5*60*1); /* walk list every 5 minutes */ ! 107: int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ ! 108: int arpt_down = 20; /* once declared down, don't send for 20 secs */ ! 109: #define rt_expire rt_rmx.rmx_expire ! 110: ! 111: static void arprequest __P((struct arpcom *, u_long *, u_long *, u_char *)); ! 112: static void arptfree __P((struct llinfo_arp *)); ! 113: static void arptimer __P((void *)); ! 114: static struct llinfo_arp *arplookup __P((u_long, int, int)); ! 115: static void in_arpinput __P((struct mbuf *)); ! 116: ! 117: extern struct ifnet loif; ! 118: struct llinfo_arp llinfo_arp = {&llinfo_arp, &llinfo_arp}; ! 119: struct ifqueue arpintrq = {0, 0, 0, 50}; ! 120: int arp_inuse, arp_allocated, arp_intimer; ! 121: int arp_maxtries = 5; ! 122: int useloopback = 1; /* use loopback interface for local traffic */ ! 123: int arpinit_done = 0; ! 124: ! 125: /* revarp state */ ! 126: static struct in_addr myip, srv_ip; ! 127: static int myip_initialized = 0; ! 128: static int revarp_in_progress = 0; ! 129: static struct ifnet *myip_ifp = NULL; ! 130: ! 131: /* Should be in spl.h */ ! 132: int splimp(void); ! 133: int splnet(void); ! 134: int splx(int); ! 135: ! 136: /* ! 137: * Timeout routine. Age arp_tab entries periodically. ! 138: */ ! 139: /* ARGSUSED */ ! 140: static void ! 141: arptimer(arg) ! 142: void *arg; ! 143: { ! 144: int s; ! 145: register struct llinfo_arp *la = llinfo_arp.la_next; ! 146: ! 147: s = splnet(); ! 148: while (la != &llinfo_arp) { ! 149: register struct rtentry *rt = la->la_rt; ! 150: la = la->la_next; ! 151: if (rt->rt_expire && rt->rt_expire <= time.tv_sec) ! 152: arptfree(la->la_prev); /* timer has expired; clear */ ! 153: } ! 154: timeout(arptimer, NULL, arpt_prune * hz); ! 155: splx(s); ! 156: ! 157: } ! 158: ! 159: /* ! 160: * Parallel to llc_rtrequest. ! 161: */ ! 162: void ! 163: arp_rtrequest(req, rt, sa) ! 164: int req; ! 165: register struct rtentry *rt; ! 166: struct sockaddr *sa; ! 167: { ! 168: register struct sockaddr *gate = rt->rt_gateway; ! 169: register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; ! 170: static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; ! 171: ! 172: if (!arpinit_done) { ! 173: arpinit_done = 1; ! 174: timeout(arptimer, (caddr_t)0, hz); ! 175: } ! 176: if (rt->rt_flags & RTF_GATEWAY) ! 177: return; ! 178: switch (req) { ! 179: ! 180: case RTM_ADD: ! 181: /* ! 182: * XXX: If this is a manually added route to interface ! 183: * such as older version of routed or gated might provide, ! 184: * restore cloning bit. ! 185: */ ! 186: if ((rt->rt_flags & RTF_HOST) == 0 && ! 187: SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) ! 188: rt->rt_flags |= RTF_CLONING; ! 189: if (rt->rt_flags & RTF_CLONING) { ! 190: /* ! 191: * Case 1: This route should come from a route to iface. ! 192: */ ! 193: rt_setgate(rt, rt_key(rt), ! 194: (struct sockaddr *)&null_sdl); ! 195: gate = rt->rt_gateway; ! 196: SDL(gate)->sdl_type = rt->rt_ifp->if_type; ! 197: SDL(gate)->sdl_index = rt->rt_ifp->if_index; ! 198: /* ! 199: * Give this route an expiration time, even though ! 200: * it's a "permanent" route, so that routes cloned ! 201: * from it do not need their expiration time set. ! 202: */ ! 203: rt->rt_expire = time.tv_sec; ! 204: break; ! 205: } ! 206: /* Announce a new entry if requested. */ ! 207: if (rt->rt_flags & RTF_ANNOUNCE) ! 208: arprequest((struct arpcom *)rt->rt_ifp, ! 209: &SIN(rt_key(rt))->sin_addr.s_addr, ! 210: &SIN(rt_key(rt))->sin_addr.s_addr, ! 211: (u_char *)LLADDR(SDL(gate))); ! 212: /*FALLTHROUGH*/ ! 213: case RTM_RESOLVE: ! 214: if (gate->sa_family != AF_LINK || ! 215: gate->sa_len < sizeof(null_sdl)) { ! 216: log(LOG_DEBUG, "arp_rtrequest: bad gateway value"); ! 217: break; ! 218: } ! 219: SDL(gate)->sdl_type = rt->rt_ifp->if_type; ! 220: SDL(gate)->sdl_index = rt->rt_ifp->if_index; ! 221: if (la != 0) ! 222: break; /* This happens on a route change */ ! 223: /* ! 224: * Case 2: This route may come from cloning, or a manual route ! 225: * add with a LL address. ! 226: */ ! 227: R_Malloc(la, struct llinfo_arp *, sizeof(*la)); ! 228: rt->rt_llinfo = (caddr_t)la; ! 229: if (la == 0) { ! 230: log(LOG_DEBUG, "arp_rtrequest: malloc failed\n"); ! 231: break; ! 232: } ! 233: arp_inuse++, arp_allocated++; ! 234: Bzero(la, sizeof(*la)); ! 235: la->la_rt = rt; ! 236: rt->rt_flags |= RTF_LLINFO; ! 237: insque((queue_t)la, (queue_t)&llinfo_arp); ! 238: if (SIN(rt_key(rt))->sin_addr.s_addr == ! 239: (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { ! 240: /* ! 241: * This test used to be ! 242: * if (loif.if_flags & IFF_UP) ! 243: * It allowed local traffic to be forced ! 244: * through the hardware by configuring the loopback down. ! 245: * However, it causes problems during network configuration ! 246: * for boards that can't receive packets they send. ! 247: * It is now necessary to clear "useloopback" and remove ! 248: * the route to force traffic out to the hardware. ! 249: */ ! 250: rt->rt_expire = 0; ! 251: Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr, ! 252: LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); ! 253: if (useloopback) ! 254: rt->rt_ifp = &loif; ! 255: ! 256: } ! 257: break; ! 258: ! 259: case RTM_DELETE: ! 260: if (la == 0) ! 261: break; ! 262: arp_inuse--; ! 263: remque((queue_t)la); ! 264: rt->rt_llinfo = 0; ! 265: rt->rt_flags &= ~RTF_LLINFO; ! 266: if (la->la_hold) ! 267: m_freem(la->la_hold); ! 268: Free((caddr_t)la); ! 269: } ! 270: } ! 271: ! 272: /* ! 273: * Broadcast an ARP packet, asking who has addr on interface ac. ! 274: */ ! 275: void ! 276: arpwhohas(ac, addr) ! 277: register struct arpcom *ac; ! 278: register struct in_addr *addr; ! 279: { struct ifnet *ifp = (struct ifnet *)ac; ! 280: struct ifaddr *ifa = ifp->if_addrlist; ! 281: ! 282: while (ifa) ! 283: { if (ifa->ifa_addr->sa_family == AF_INET) ! 284: { arprequest(ac, &SIN(ifa->ifa_addr)->sin_addr.s_addr, &addr->s_addr, ac->ac_enaddr); ! 285: return; ! 286: } ! 287: ifa = ifa->ifa_next; ! 288: } ! 289: return; /* XXX */ ! 290: } ! 291: ! 292: /* ! 293: * Broadcast an ARP request. Caller specifies: ! 294: * - arp header source ip address ! 295: * - arp header target ip address ! 296: * - arp header source ethernet address ! 297: */ ! 298: static void ! 299: arprequest(ac, sip, tip, enaddr) ! 300: register struct arpcom *ac; ! 301: register u_long *sip, *tip; ! 302: register u_char *enaddr; ! 303: { ! 304: register struct mbuf *m; ! 305: register struct ether_header *eh; ! 306: register struct ether_arp *ea; ! 307: struct sockaddr sa; ! 308: ! 309: if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) ! 310: return; ! 311: m->m_len = sizeof(*ea); ! 312: m->m_pkthdr.len = sizeof(*ea); ! 313: MH_ALIGN(m, sizeof(*ea)); ! 314: ea = mtod(m, struct ether_arp *); ! 315: eh = (struct ether_header *)sa.sa_data; ! 316: bzero((caddr_t)ea, sizeof (*ea)); ! 317: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, ! 318: sizeof(eh->ether_dhost)); ! 319: eh->ether_type = htons(ETHERTYPE_ARP); ! 320: ea->arp_hrd = htons(ARPHRD_ETHER); ! 321: ea->arp_pro = htons(ETHERTYPE_IP); ! 322: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ ! 323: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ ! 324: ea->arp_op = htons(ARPOP_REQUEST); ! 325: bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); ! 326: bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); ! 327: bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa)); ! 328: sa.sa_family = AF_UNSPEC; ! 329: sa.sa_len = sizeof(sa); ! 330: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); ! 331: } ! 332: ! 333: /* ! 334: * Resolve an IP address into an ethernet address. If success, ! 335: * desten is filled in. If there is no entry in arptab, ! 336: * set one up and broadcast a request for the IP address. ! 337: * Hold onto this mbuf and resend it once the address ! 338: * is finally resolved. A return value of 1 indicates ! 339: * that desten has been filled in and the packet should be sent ! 340: * normally; a 0 return indicates that the packet has been ! 341: * taken over here, either now or for later transmission. ! 342: */ ! 343: int ! 344: arpresolve(ac, rt, m, dst, desten) ! 345: register struct arpcom *ac; ! 346: register struct rtentry *rt; ! 347: struct mbuf *m; ! 348: register struct sockaddr *dst; ! 349: register u_char *desten; ! 350: { ! 351: register struct llinfo_arp *la; ! 352: struct sockaddr_dl *sdl; ! 353: ! 354: if (m->m_flags & M_BCAST) { /* broadcast */ ! 355: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten, ! 356: sizeof(etherbroadcastaddr)); ! 357: return (1); ! 358: } ! 359: if (m->m_flags & M_MCAST) { /* multicast */ ! 360: ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); ! 361: return(1); ! 362: } ! 363: if (rt) ! 364: la = (struct llinfo_arp *)rt->rt_llinfo; ! 365: else { ! 366: if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0))) ! 367: rt = la->la_rt; ! 368: } ! 369: if (la == 0 || rt == 0) { ! 370: log(LOG_DEBUG, "arpresolve: can't allocate llinfo"); ! 371: m_freem(m); ! 372: return (0); ! 373: } ! 374: sdl = SDL(rt->rt_gateway); ! 375: /* ! 376: * Check the address family and length is valid, the address ! 377: * is resolved; otherwise, try to resolve. ! 378: */ ! 379: if ((rt->rt_expire == 0 || rt->rt_expire > time.tv_sec) && ! 380: sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { ! 381: bcopy(LLADDR(sdl), desten, sdl->sdl_alen); ! 382: ! 383: return 1; ! 384: } ! 385: /* ! 386: * There is an arptab entry, but no ethernet address ! 387: * response yet. Replace the held mbuf with this ! 388: * latest one. ! 389: */ ! 390: if (la->la_hold) ! 391: m_freem(la->la_hold); ! 392: la->la_hold = m; ! 393: /* ! 394: * Re-send the ARP request when appropriate. ! 395: */ ! 396: #if DIAGNOSTIC ! 397: if (rt->rt_expire == 0) { ! 398: /* This should never happen. (Should it? -gwr) */ ! 399: printf("arpresolve: unresolved and rt_expire == 0\n"); ! 400: /* Set expiration time to now (expired). */ ! 401: rt->rt_expire = time.tv_sec; ! 402: } ! 403: #endif ! 404: if (rt->rt_expire) { ! 405: rt->rt_flags &= ~RTF_REJECT; ! 406: if (la->la_asked == 0 || rt->rt_expire != time.tv_sec) { ! 407: rt->rt_expire = time.tv_sec; ! 408: if (la->la_asked++ < arp_maxtries) ! 409: arpwhohas(ac, &(SIN(dst)->sin_addr)); ! 410: else { ! 411: rt->rt_flags |= RTF_REJECT; ! 412: rt->rt_expire += arpt_down; ! 413: la->la_asked = 0; ! 414: } ! 415: } ! 416: } ! 417: return (0); ! 418: } ! 419: ! 420: /* ! 421: * Common length and type checks are done here, ! 422: * then the protocol-specific routine is called. ! 423: */ ! 424: void ! 425: arpintr() ! 426: { ! 427: register struct mbuf *m; ! 428: register struct arphdr *ar; ! 429: int s; ! 430: ! 431: while (arpintrq.ifq_head) { ! 432: s = splimp(); ! 433: IF_DEQUEUE(&arpintrq, m); ! 434: splx(s); ! 435: if (m == 0 || (m->m_flags & M_PKTHDR) == 0) ! 436: panic("arpintr"); ! 437: if (m->m_len >= sizeof(struct arphdr) && ! 438: (ar = mtod(m, struct arphdr *)) && ! 439: ntohs(ar->ar_hrd) == ARPHRD_ETHER && ! 440: m->m_len >= ! 441: sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) ! 442: switch (ntohs(ar->ar_pro)) { ! 443: ! 444: case ETHERTYPE_IP: ! 445: case ETHERTYPE_IPTRAILERS: ! 446: in_arpinput(m); ! 447: continue; ! 448: } ! 449: ! 450: m_freem(m); ! 451: } ! 452: } ! 453: ! 454: /* ! 455: * ARP for Internet protocols on 10 Mb/s Ethernet. ! 456: * Algorithm is that given in RFC 826. ! 457: * In addition, a sanity check is performed on the sender ! 458: * protocol address, to catch impersonators. ! 459: * We no longer handle negotiations for use of trailer protocol: ! 460: * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent ! 461: * along with IP replies if we wanted trailers sent to us, ! 462: * and also sent them in response to IP replies. ! 463: * This allowed either end to announce the desire to receive ! 464: * trailer packets. ! 465: * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, ! 466: * but formerly didn't normally send requests. ! 467: */ ! 468: static void ! 469: in_arpinput(m) ! 470: struct mbuf *m; ! 471: { ! 472: register struct ether_arp *ea; ! 473: register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif; ! 474: struct ether_header *eh; ! 475: register struct llinfo_arp *la = 0; ! 476: register struct rtentry *rt; ! 477: struct in_ifaddr *ia, *maybe_ia = 0; ! 478: struct sockaddr_dl *sdl; ! 479: struct sockaddr sa; ! 480: struct in_addr isaddr, itaddr, myaddr; ! 481: int op; ! 482: extern void kprintf( const char *, ...); ! 483: ! 484: ea = mtod(m, struct ether_arp *); ! 485: op = ntohs(ea->arp_op); ! 486: bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr)); ! 487: bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr)); ! 488: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 489: if (ia->ia_ifp == &ac->ac_if) { ! 490: maybe_ia = ia; ! 491: if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) || ! 492: (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)) ! 493: break; ! 494: } ! 495: if (maybe_ia == 0) ! 496: goto out; ! 497: myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr; ! 498: #if 0 ! 499: /* ! 500: * In order to support BlueBox networking, we need to allow ! 501: * "self-addressed" stamped envelopes ! 502: */ ! 503: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr, ! 504: sizeof (ea->arp_sha))) ! 505: goto out; /* it's from me, ignore it. */ ! 506: #endif ! 507: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr, ! 508: sizeof (ea->arp_sha))) { ! 509: log(LOG_ERR, ! 510: "arp: ether address is broadcast for IP address %x!\n", ! 511: ntohl(isaddr.s_addr)); ! 512: goto out; ! 513: } ! 514: if (isaddr.s_addr == myaddr.s_addr) { ! 515: log(LOG_ERR, ! 516: "duplicate IP address %08x sent from ethernet address %s\n", ! 517: ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha)); ! 518: itaddr = myaddr; ! 519: goto reply; ! 520: } ! 521: la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0); ! 522: if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) { ! 523: if (sdl->sdl_alen && ! 524: bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) ! 525: log(LOG_INFO, "arp info overwritten for %08x by %s\n", ! 526: ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha)); ! 527: bcopy((caddr_t)ea->arp_sha, LLADDR(sdl), ! 528: sdl->sdl_alen = sizeof(ea->arp_sha)); ! 529: if (rt->rt_expire) ! 530: rt->rt_expire = time.tv_sec + arpt_keep; ! 531: rt->rt_flags &= ~RTF_REJECT; ! 532: la->la_asked = 0; ! 533: if (la->la_hold) { ! 534: (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold, ! 535: rt_key(rt), rt); ! 536: la->la_hold = 0; ! 537: } ! 538: } ! 539: reply: ! 540: if (op != ARPOP_REQUEST) { ! 541: out: ! 542: m_freem(m); ! 543: return; ! 544: } ! 545: if (itaddr.s_addr == myaddr.s_addr) { ! 546: /* I am the target */ ! 547: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, ! 548: sizeof(ea->arp_sha)); ! 549: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, ! 550: sizeof(ea->arp_sha)); ! 551: } else { ! 552: la = arplookup(itaddr.s_addr, 0, SIN_PROXY); ! 553: if (la == NULL) ! 554: goto out; ! 555: rt = la->la_rt; ! 556: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha, ! 557: sizeof(ea->arp_sha)); ! 558: sdl = SDL(rt->rt_gateway); ! 559: bcopy(LLADDR(sdl), (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); ! 560: } ! 561: ! 562: bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa)); ! 563: bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); ! 564: ea->arp_op = htons(ARPOP_REPLY); ! 565: ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ ! 566: eh = (struct ether_header *)sa.sa_data; ! 567: bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost, ! 568: sizeof(eh->ether_dhost)); ! 569: eh->ether_type = htons(ETHERTYPE_ARP); ! 570: sa.sa_family = AF_UNSPEC; ! 571: sa.sa_len = sizeof(sa); ! 572: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0); ! 573: return; ! 574: } ! 575: ! 576: /* ! 577: * Free an arp entry. ! 578: */ ! 579: static void ! 580: arptfree(la) ! 581: register struct llinfo_arp *la; ! 582: { ! 583: register struct rtentry *rt = la->la_rt; ! 584: register struct sockaddr_dl *sdl; ! 585: ! 586: if (rt == 0) ! 587: panic("arptfree"); ! 588: if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) && ! 589: sdl->sdl_family == AF_LINK) { ! 590: sdl->sdl_alen = 0; ! 591: la->la_asked = 0; ! 592: rt->rt_flags &= ~RTF_REJECT; ! 593: return; ! 594: } ! 595: rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt), ! 596: 0, (struct rtentry **)0); ! 597: } ! 598: ! 599: /* ! 600: * Lookup or enter a new address in arptab. ! 601: */ ! 602: static struct llinfo_arp * ! 603: arplookup(addr, create, proxy) ! 604: u_long addr; ! 605: int create, proxy; ! 606: { ! 607: register struct rtentry *rt; ! 608: static struct sockaddr_inarp sin = {sizeof(sin), AF_INET }; ! 609: ! 610: sin.sin_addr.s_addr = addr; ! 611: sin.sin_other = proxy ? SIN_PROXY : 0; ! 612: rt = rtalloc1((struct sockaddr *)&sin, create); ! 613: if (rt == 0) ! 614: return (0); ! 615: rt->rt_refcnt--; ! 616: if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || ! 617: rt->rt_gateway->sa_family != AF_LINK) { ! 618: if (create) ! 619: log(LOG_DEBUG, "arplookup: unable to enter address for %x\n", ntohl(addr)); ! 620: return (0); ! 621: } ! 622: return ((struct llinfo_arp *)rt->rt_llinfo); ! 623: } ! 624: ! 625: int ! 626: arpioctl(cmd, data) ! 627: u_long cmd; ! 628: caddr_t data; ! 629: { ! 630: ! 631: return (EOPNOTSUPP); ! 632: } ! 633: ! 634: void ! 635: arp_ifinit(ac, ifa) ! 636: struct arpcom *ac; ! 637: struct ifaddr *ifa; ! 638: { ! 639: ac->ac_ipaddr = IA_SIN(ifa)->sin_addr; ! 640: /* Warn the user if another station has this IP address. */ ! 641: arpwhohas(ac, &ac->ac_ipaddr); ! 642: ifa->ifa_rtrequest = arp_rtrequest; ! 643: ifa->ifa_flags |= RTF_CLONING; ! 644: } ! 645: ! 646: /* ! 647: * Called from 10 Mb/s Ethernet interrupt handlers ! 648: * when ether packet type ETHERTYPE_REVARP ! 649: * is received. Common length and type checks are done here, ! 650: * then the protocol-specific routine is called. ! 651: */ ! 652: void ! 653: revarpinput(m) ! 654: struct mbuf *m; ! 655: { ! 656: struct arphdr *ar; ! 657: extern int in_revarpinput(struct mbuf *); ! 658: ! 659: if (m->m_len < sizeof(struct arphdr)) { ! 660: goto out; ! 661: } ! 662: ar = mtod(m, struct arphdr *); ! 663: if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) { ! 664: goto out; ! 665: } ! 666: if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) { ! 667: goto out; ! 668: } ! 669: switch (ntohs(ar->ar_pro)) { ! 670: ! 671: case ETHERTYPE_IP: ! 672: case ETHERTYPE_IPTRAILERS: ! 673: in_revarpinput(m); ! 674: return; ! 675: ! 676: default: ! 677: break; ! 678: } ! 679: out: ! 680: m_freem(m); ! 681: } ! 682: ! 683: /* ! 684: * RARP for Internet protocols on 10 Mb/s Ethernet. ! 685: * Algorithm is that given in RFC 903. ! 686: * We are only using for bootstrap purposes to get an ip address for one of ! 687: * our interfaces. Thus we support no user-interface. ! 688: * ! 689: * Since the contents of the RARP reply are specific to the interface that ! 690: * sent the request, this code must ensure that they are properly associated. ! 691: * ! 692: * Note: also supports ARP via RARP packets, per the RFC. ! 693: */ ! 694: int ! 695: in_revarpinput(m) ! 696: struct mbuf *m; ! 697: { ! 698: struct ifnet *ifp; ! 699: struct ether_arp *ar; ! 700: int op; ! 701: extern void wakeup (void *); ! 702: ! 703: ar = mtod(m, struct ether_arp *); ! 704: op = ntohs(ar->arp_op); ! 705: switch (op) { ! 706: case ARPOP_REQUEST: ! 707: case ARPOP_REPLY: /* per RFC */ ! 708: in_arpinput(m); ! 709: return(0); ! 710: case ARPOP_REVREPLY: ! 711: break; ! 712: case ARPOP_REVREQUEST: /* handled by rarpd(8) */ ! 713: default: ! 714: goto out; ! 715: } ! 716: if (!revarp_in_progress) ! 717: goto out; ! 718: ifp = m->m_pkthdr.rcvif; ! 719: if (ifp != myip_ifp) /* !same interface */ ! 720: goto out; ! 721: if (myip_initialized) ! 722: goto wake; ! 723: if (bcmp(ar->arp_tha, ((struct arpcom *)ifp)->ac_enaddr, ! 724: sizeof(ar->arp_tha))) ! 725: goto out; ! 726: bcopy((caddr_t)ar->arp_spa, (caddr_t)&srv_ip, sizeof(srv_ip)); ! 727: bcopy((caddr_t)ar->arp_tpa, (caddr_t)&myip, sizeof(myip)); ! 728: myip_initialized = 1; ! 729: wake: /* Do wakeup every time in case it was missed. */ ! 730: wakeup((caddr_t)&myip); ! 731: ! 732: out: ! 733: m_freem(m); ! 734: return(0); ! 735: } ! 736: ! 737: /* ! 738: * Send a RARP request for the ip address of the specified interface. ! 739: * The request should be RFC 903-compliant. ! 740: */ ! 741: void ! 742: revarprequest(ifp) ! 743: struct ifnet *ifp; ! 744: { ! 745: struct sockaddr sa; ! 746: struct mbuf *m; ! 747: struct ether_header *eh; ! 748: struct ether_arp *ea; ! 749: struct arpcom *ac = (struct arpcom *)ifp; ! 750: ! 751: if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) ! 752: return; ! 753: m->m_len = sizeof(*ea); ! 754: m->m_pkthdr.len = sizeof(*ea); ! 755: MH_ALIGN(m, sizeof(*ea)); ! 756: ea = mtod(m, struct ether_arp *); ! 757: eh = (struct ether_header *)sa.sa_data; ! 758: bzero((caddr_t)ea, sizeof(*ea)); ! 759: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, ! 760: sizeof(eh->ether_dhost)); ! 761: eh->ether_type = htons(ETHERTYPE_REVARP); ! 762: ea->arp_hrd = htons(ARPHRD_ETHER); ! 763: ea->arp_pro = htons(ETHERTYPE_IP); ! 764: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ ! 765: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ ! 766: ea->arp_op = htons(ARPOP_REVREQUEST); ! 767: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha, ! 768: sizeof(ea->arp_sha)); ! 769: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_tha, ! 770: sizeof(ea->arp_tha)); ! 771: sa.sa_family = AF_UNSPEC; ! 772: sa.sa_len = sizeof(sa); ! 773: ifp->if_output(ifp, m, &sa, (struct rtentry *)0); ! 774: } ! 775: ! 776: /* ! 777: * RARP for the ip address of the specified interface, but also ! 778: * save the ip address of the server that sent the answer. ! 779: * Timeout if no response is received. ! 780: */ ! 781: int ! 782: revarpwhoarewe(ifp, serv_in, clnt_in) ! 783: struct ifnet *ifp; ! 784: struct in_addr *serv_in; ! 785: struct in_addr *clnt_in; ! 786: { ! 787: int result, count = 20; ! 788: extern int tsleep(void *, int, char *, int); ! 789: ! 790: if (myip_initialized) ! 791: return EIO; ! 792: ! 793: myip_ifp = ifp; ! 794: revarp_in_progress = 1; ! 795: while (count--) { ! 796: revarprequest(ifp); ! 797: result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2); ! 798: if (result != EWOULDBLOCK) ! 799: break; ! 800: } ! 801: revarp_in_progress = 0; ! 802: if (!myip_initialized) ! 803: return ENETUNREACH; ! 804: ! 805: bcopy((caddr_t)&srv_ip, serv_in, sizeof(*serv_in)); ! 806: bcopy((caddr_t)&myip, clnt_in, sizeof(*clnt_in)); ! 807: return 0; ! 808: } ! 809: ! 810: /* For compatibility: only saves interface address. */ ! 811: int ! 812: revarpwhoami(in, ifp) ! 813: struct in_addr *in; ! 814: struct ifnet *ifp; ! 815: { ! 816: struct in_addr server; ! 817: return (revarpwhoarewe(ifp, &server, in)); ! 818: } ! 819: ! 820: ! 821: #ifdef DDB ! 822: static void ! 823: db_print_sa(sa) ! 824: struct sockaddr *sa; ! 825: { ! 826: int len; ! 827: u_char *p; ! 828: ! 829: if (sa == 0) { ! 830: db_printf("[NULL]"); ! 831: return; ! 832: } ! 833: ! 834: p = (u_char*)sa; ! 835: len = sa->sa_len; ! 836: db_printf("["); ! 837: while (len > 0) { ! 838: db_printf("%d", *p); ! 839: p++; len--; ! 840: if (len) db_printf(","); ! 841: } ! 842: db_printf("]\n"); ! 843: } ! 844: static void ! 845: db_print_ifa(ifa) ! 846: struct ifaddr *ifa; ! 847: { ! 848: if (ifa == 0) ! 849: return; ! 850: db_printf(" ifa_addr="); ! 851: db_print_sa(ifa->ifa_addr); ! 852: db_printf(" ifa_dsta="); ! 853: db_print_sa(ifa->ifa_dstaddr); ! 854: db_printf(" ifa_mask="); ! 855: db_print_sa(ifa->ifa_netmask); ! 856: db_printf(" flags=0x%x,refcnt=%d,metric=%d\n", ! 857: ifa->ifa_flags, ! 858: ifa->ifa_refcnt, ! 859: ifa->ifa_metric); ! 860: } ! 861: static void ! 862: db_print_llinfo(li) ! 863: caddr_t li; ! 864: { ! 865: struct llinfo_arp *la; ! 866: ! 867: if (li == 0) ! 868: return; ! 869: la = (struct llinfo_arp *)li; ! 870: db_printf(" la_rt=0x%x la_hold=0x%x, la_asked=0x%x\n", ! 871: la->la_rt, la->la_hold, la->la_asked); ! 872: } ! 873: /* ! 874: * Function to pass to rn_walktree(). ! 875: * Return non-zero error to abort walk. ! 876: */ ! 877: static int ! 878: db_show_radix_node(rn, w) ! 879: struct radix_node *rn; ! 880: void *w; ! 881: { ! 882: struct rtentry *rt = (struct rtentry *)rn; ! 883: ! 884: db_printf("rtentry=0x%x", rt); ! 885: ! 886: db_printf(" flags=0x%x refcnt=%d use=%d expire=%d\n", ! 887: rt->rt_flags, rt->rt_refcnt, ! 888: rt->rt_use, rt->rt_expire); ! 889: ! 890: db_printf(" key="); db_print_sa(rt_key(rt)); ! 891: db_printf(" mask="); db_print_sa(rt_mask(rt)); ! 892: db_printf(" gw="); db_print_sa(rt->rt_gateway); ! 893: ! 894: db_printf(" ifp=0x%x ", rt->rt_ifp); ! 895: if (rt->rt_ifp) ! 896: db_printf("(%s%d)", ! 897: rt->rt_ifp->if_name, ! 898: rt->rt_ifp->if_unit); ! 899: else ! 900: db_printf("(NULL)"); ! 901: ! 902: db_printf(" ifa=0x%x\n", rt->rt_ifa); ! 903: db_print_ifa(rt->rt_ifa); ! 904: ! 905: db_printf(" genmask="); db_print_sa(rt->rt_genmask); ! 906: ! 907: db_printf(" gwroute=0x%x llinfo=0x%x\n", ! 908: rt->rt_gwroute, rt->rt_llinfo); ! 909: db_print_llinfo(rt->rt_llinfo); ! 910: ! 911: return (0); ! 912: } ! 913: /* ! 914: * Function to print all the route trees. ! 915: * Use this from ddb: "call db_show_arptab" ! 916: */ ! 917: db_show_arptab() ! 918: { ! 919: struct radix_node_head *rnh; ! 920: rnh = rt_tables[AF_INET]; ! 921: db_printf("Route tree for AF_INET\n"); ! 922: if (rnh == NULL) { ! 923: db_printf(" (not initialized)\n"); ! 924: return (0); ! 925: } ! 926: rn_walktree(rnh, db_show_radix_node, NULL); ! 927: return (0); ! 928: } ! 929: #endif ! 930: #endif /* INET */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.