if_ether.c revision 128636
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1982, 1986, 1988, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 4. Neither the name of the University nor the names of its contributors 141541Srgrimes * may be used to endorse or promote products derived from this software 151541Srgrimes * without specific prior written permission. 161541Srgrimes * 171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271541Srgrimes * SUCH DAMAGE. 281541Srgrimes * 291541Srgrimes * @(#)if_ether.c 8.1 (Berkeley) 6/10/93 301541Srgrimes * $FreeBSD: head/sys/netinet/if_ether.c 128636 2004-04-25 09:24:52Z luigi $ 311541Srgrimes */ 321541Srgrimes 331541Srgrimes/* 341541Srgrimes * Ethernet address resolution protocol. 351541Srgrimes * TODO: 361541Srgrimes * add "inuse/lock" bit (or ref. count) along with valid bit 371541Srgrimes */ 381541Srgrimes 3924453Speter#include "opt_inet.h" 401541Srgrimes#include "opt_bdg.h" 411541Srgrimes#include "opt_mac.h" 421541Srgrimes 431541Srgrimes#include <sys/param.h> 441541Srgrimes#include <sys/kernel.h> 451541Srgrimes#include <sys/queue.h> 461541Srgrimes#include <sys/sysctl.h> 471541Srgrimes#include <sys/systm.h> 481541Srgrimes#include <sys/mac.h> 4912221Sbde#include <sys/mbuf.h> 501541Srgrimes#include <sys/malloc.h> 511541Srgrimes#include <sys/socket.h> 521541Srgrimes#include <sys/syslog.h> 531541Srgrimes 541541Srgrimes#include <net/if.h> 5518013Sbde#include <net/if_dl.h> 561541Srgrimes#include <net/if_types.h> 5712221Sbde#include <net/route.h> 5811332Sswallace#include <net/netisr.h> 591541Srgrimes#include <net/if_llc.h> 601541Srgrimes#ifdef BRIDGE 6112221Sbde#include <net/ethernet.h> 621541Srgrimes#include <net/bridge.h> 631541Srgrimes#endif 641549Srgrimes 651541Srgrimes#include <netinet/in.h> 661541Srgrimes#include <netinet/in_var.h> 6711332Sswallace#include <netinet/if_ether.h> 681541Srgrimes 691541Srgrimes#include <net/if_arc.h> 701541Srgrimes#include <net/iso88025.h> 711541Srgrimes 721541Srgrimes#define SIN(s) ((struct sockaddr_in *)s) 731541Srgrimes#define SDL(s) ((struct sockaddr_dl *)s) 741541Srgrimes 751541SrgrimesSYSCTL_DECL(_net_link_ether); 761541SrgrimesSYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); 771541Srgrimes 7812221Sbde/* timer values */ 7911332Sswallacestatic int arpt_prune = (5*60*1); /* walk list every 5 minutes */ 8011332Sswallacestatic int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ 8111332Sswallacestatic int arpt_down = 20; /* once declared down, don't send for 20 sec */ 8212221Sbde 831541SrgrimesSYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW, 841549Srgrimes &arpt_prune, 0, ""); 851541SrgrimesSYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, 861541Srgrimes &arpt_keep, 0, ""); 8711332SswallaceSYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time, CTLFLAG_RW, 881541Srgrimes &arpt_down, 0, ""); 891541Srgrimes 901541Srgrimes#define rt_expire rt_rmx.rmx_expire 911541Srgrimes 921541Srgrimesstruct llinfo_arp { 931541Srgrimes LIST_ENTRY(llinfo_arp) la_le; 941541Srgrimes struct rtentry *la_rt; 951541Srgrimes struct mbuf *la_hold; /* last packet until resolved/timeout */ 9612221Sbde u_short la_preempt; /* countdown for pre-expiry arps */ 9711332Sswallace u_short la_asked; /* #times we QUERIED following expiration */ 9811332Sswallace#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */ 9911332Sswallace}; 10012221Sbde 10111332Sswallacestatic LIST_HEAD(, llinfo_arp) llinfo_arp; 1021549Srgrimes 1031541Srgrimesstatic struct ifqueue arpintrq; 1041541Srgrimesstatic int arp_allocated; 10511332Sswallacestatic int arpinit_done; 1061541Srgrimes 1071541Srgrimesstatic int arp_maxtries = 5; 1081541Srgrimesstatic int useloopback = 1; /* use loopback interface for local traffic */ 1091541Srgrimesstatic int arp_proxyall = 0; 1101541Srgrimesstatic struct callout arp_callout; 1111541Srgrimes 1121541SrgrimesSYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, 11312221Sbde &arp_maxtries, 0, ""); 11411332SswallaceSYSCTL_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW, 11511332Sswallace &useloopback, 0, ""); 11611332SswallaceSYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, 11712221Sbde &arp_proxyall, 0, ""); 11811332Sswallace 1191541Srgrimesstatic void arp_init(void); 1201549Srgrimesstatic void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *); 1211541Srgrimesstatic void arprequest(struct ifnet *, 1221541Srgrimes struct in_addr *, struct in_addr *, u_char *); 12311332Sswallacestatic void arpintr(struct mbuf *); 1241541Srgrimesstatic void arptfree(struct llinfo_arp *); 1251541Srgrimesstatic void arptimer(void *); 1261541Srgrimesstatic struct llinfo_arp 1271541Srgrimes *arplookup(u_long, int, int); 1281541Srgrimes#ifdef INET 1291541Srgrimesstatic void in_arpinput(struct mbuf *); 1301541Srgrimes#endif 1311541Srgrimes 1321541Srgrimes/* 1331541Srgrimes * Timeout routine. Age arp_tab entries periodically. 13412221Sbde */ 13511332Sswallace/* ARGSUSED */ 13611332Sswallacestatic void 13711332Sswallacearptimer(ignored_arg) 13812221Sbde void *ignored_arg; 13911332Sswallace{ 1401541Srgrimes struct llinfo_arp *la, *ola; 1411549Srgrimes 1421541Srgrimes RADIX_NODE_HEAD_LOCK(rt_tables[AF_INET]); 1431541Srgrimes la = LIST_FIRST(&llinfo_arp); 14411332Sswallace while (la != NULL) { 1451541Srgrimes struct rtentry *rt = la->la_rt; 1461541Srgrimes ola = la; 1471541Srgrimes la = LIST_NEXT(la, la_le); 1481541Srgrimes if (rt->rt_expire && rt->rt_expire <= time_second) 1491541Srgrimes arptfree(ola); /* timer has expired, clear */ 1501541Srgrimes } 1511541Srgrimes RADIX_NODE_HEAD_UNLOCK(rt_tables[AF_INET]); 15212221Sbde 15311332Sswallace callout_reset(&arp_callout, arpt_prune * hz, arptimer, NULL); 15411332Sswallace} 15511332Sswallace 15612221Sbde/* 15711332Sswallace * Parallel to llc_rtrequest. 1581541Srgrimes */ 1591549Srgrimesstatic void 1601541Srgrimesarp_rtrequest(req, rt, info) 1611541Srgrimes int req; 16211332Sswallace struct rtentry *rt; 1631541Srgrimes struct rt_addrinfo *info; 1641541Srgrimes{ 1651541Srgrimes struct sockaddr *gate; 1661541Srgrimes struct llinfo_arp *la; 1671541Srgrimes static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; 1681541Srgrimes 1691541Srgrimes RT_LOCK_ASSERT(rt); 1701541Srgrimes 1711541Srgrimes if (!arpinit_done) { 1721541Srgrimes arpinit_done = 1; 1731541Srgrimes callout_reset(&arp_callout, hz, arptimer, NULL); 1741541Srgrimes } 1751541Srgrimes if (rt->rt_flags & RTF_GATEWAY) 1761541Srgrimes return; 1771541Srgrimes gate = rt->rt_gateway; 17812221Sbde la = (struct llinfo_arp *)rt->rt_llinfo; 17911332Sswallace switch (req) { 18011332Sswallace 18111332Sswallace case RTM_ADD: 18212221Sbde /* 18311332Sswallace * XXX: If this is a manually added route to interface 1841541Srgrimes * such as older version of routed or gated might provide, 1851549Srgrimes * restore cloning bit. 1861541Srgrimes */ 1871541Srgrimes if ((rt->rt_flags & RTF_HOST) == 0 && 18811332Sswallace SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) 1891541Srgrimes rt->rt_flags |= RTF_CLONING; 1901541Srgrimes if (rt->rt_flags & RTF_CLONING) { 1911541Srgrimes /* 1921541Srgrimes * Case 1: This route should come from a route to iface. 1931541Srgrimes */ 1941541Srgrimes rt_setgate(rt, rt_key(rt), 1951541Srgrimes (struct sockaddr *)&null_sdl); 19612221Sbde gate = rt->rt_gateway; 1971541Srgrimes SDL(gate)->sdl_type = rt->rt_ifp->if_type; 1981541Srgrimes SDL(gate)->sdl_index = rt->rt_ifp->if_index; 1991541Srgrimes rt->rt_expire = time_second; 2001541Srgrimes break; 20112221Sbde } 2021549Srgrimes /* Announce a new entry if requested. */ 2031541Srgrimes if (rt->rt_flags & RTF_ANNOUNCE) 2041541Srgrimes arprequest(rt->rt_ifp, 2051541Srgrimes &SIN(rt_key(rt))->sin_addr, 2061541Srgrimes &SIN(rt_key(rt))->sin_addr, 2071541Srgrimes (u_char *)LLADDR(SDL(gate))); 2081541Srgrimes /*FALLTHROUGH*/ 2091541Srgrimes case RTM_RESOLVE: 2101541Srgrimes if (gate->sa_family != AF_LINK || 2111541Srgrimes gate->sa_len < sizeof(null_sdl)) { 2121541Srgrimes log(LOG_DEBUG, "%s: bad gateway %s%s\n", __func__, 2131541Srgrimes inet_ntoa(SIN(rt_key(rt))->sin_addr), 2141541Srgrimes (gate->sa_family != AF_LINK) ? 2151541Srgrimes " (!AF_LINK)": ""); 2161541Srgrimes break; 2171541Srgrimes } 2181541Srgrimes SDL(gate)->sdl_type = rt->rt_ifp->if_type; 2193098Sphk SDL(gate)->sdl_index = rt->rt_ifp->if_index; 2203098Sphk if (la != 0) 2211541Srgrimes break; /* This happens on a route change */ 2221541Srgrimes /* 2231541Srgrimes * Case 2: This route may come from cloning, or a manual route 2241541Srgrimes * add with a LL address. 2251541Srgrimes */ 22612221Sbde R_Zalloc(la, struct llinfo_arp *, sizeof(*la)); 22712207Sbde rt->rt_llinfo = (caddr_t)la; 22811332Sswallace if (la == 0) { 22911332Sswallace log(LOG_DEBUG, "%s: malloc failed\n", __func__); 23012221Sbde break; 23111332Sswallace } 2321541Srgrimes arp_allocated++; 2331549Srgrimes la->la_rt = rt; 2341541Srgrimes rt->rt_flags |= RTF_LLINFO; 2351541Srgrimes RADIX_NODE_HEAD_LOCK_ASSERT(rt_tables[AF_INET]); 23612207Sbde LIST_INSERT_HEAD(&llinfo_arp, la, la_le); 2371541Srgrimes 2381541Srgrimes#ifdef INET 2391541Srgrimes /* 2401541Srgrimes * This keeps the multicast addresses from showing up 2411541Srgrimes * in `arp -a' listings as unresolved. It's not actually 2421541Srgrimes * functional. Then the same for broadcast. 2431541Srgrimes */ 2441541Srgrimes if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr)) && 2451541Srgrimes rt->rt_ifp->if_type != IFT_ARCNET) { 2461541Srgrimes ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr, 2471541Srgrimes LLADDR(SDL(gate))); 2481541Srgrimes SDL(gate)->sdl_alen = 6; 2491541Srgrimes rt->rt_expire = 0; 2501541Srgrimes } 2511541Srgrimes if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) { 2521541Srgrimes memcpy(LLADDR(SDL(gate)), rt->rt_ifp->if_broadcastaddr, 2531541Srgrimes rt->rt_ifp->if_addrlen); 2541541Srgrimes SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen; 2551541Srgrimes rt->rt_expire = 0; 2561541Srgrimes } 2571541Srgrimes#endif 2581541Srgrimes 2591541Srgrimes if (SIN(rt_key(rt))->sin_addr.s_addr == 2601541Srgrimes (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { 2611541Srgrimes /* 26212221Sbde * This test used to be 2631541Srgrimes * if (loif.if_flags & IFF_UP) 2641541Srgrimes * It allowed local traffic to be forced 2651541Srgrimes * through the hardware by configuring the loopback down. 2661541Srgrimes * However, it causes problems during network configuration 26712221Sbde * for boards that can't receive packets they send. 2681541Srgrimes * It is now necessary to clear "useloopback" and remove 2691549Srgrimes * the route to force traffic out to the hardware. 2701541Srgrimes */ 2711541Srgrimes rt->rt_expire = 0; 2721541Srgrimes bcopy(IF_LLADDR(rt->rt_ifp), LLADDR(SDL(gate)), 2731541Srgrimes SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen); 2741541Srgrimes if (useloopback) 2751541Srgrimes rt->rt_ifp = loif; 2761541Srgrimes 2771541Srgrimes } 27820677Sbde break; 27920677Sbde 2801541Srgrimes case RTM_DELETE: 2811541Srgrimes if (la == 0) 2821541Srgrimes break; 28315985Sdg RADIX_NODE_HEAD_LOCK_ASSERT(rt_tables[AF_INET]); 2841541Srgrimes LIST_REMOVE(la, la_le); 2851541Srgrimes rt->rt_llinfo = 0; 2861541Srgrimes rt->rt_flags &= ~RTF_LLINFO; 2871541Srgrimes if (la->la_hold) 2881541Srgrimes m_freem(la->la_hold); 2891541Srgrimes Free((caddr_t)la); 2901541Srgrimes } 2911541Srgrimes} 2921541Srgrimes 2931541Srgrimes/* 2941541Srgrimes * Broadcast an ARP request. Caller specifies: 2951541Srgrimes * - arp header source ip address 2961541Srgrimes * - arp header target ip address 2971541Srgrimes * - arp header source ethernet address 2981541Srgrimes */ 2991541Srgrimesstatic void 30024448Speterarprequest(ifp, sip, tip, enaddr) 30124448Speter struct ifnet *ifp; 30224448Speter struct in_addr *sip, *tip; 30324448Speter u_char *enaddr; 30424448Speter{ 30524448Speter struct mbuf *m; 30624448Speter struct arphdr *ah; 30724448Speter struct sockaddr sa; 30824448Speter 30924448Speter if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) 31024448Speter return; 31124448Speter m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) + 31212221Sbde 2*ifp->if_data.ifi_addrlen; 3131541Srgrimes m->m_pkthdr.len = m->m_len; 3141541Srgrimes MH_ALIGN(m, m->m_len); 3151541Srgrimes ah = mtod(m, struct arphdr *); 31612221Sbde bzero((caddr_t)ah, m->m_len); 3171541Srgrimes#ifdef MAC 3181549Srgrimes mac_create_mbuf_linklayer(ifp, m); 3191541Srgrimes#endif 3201541Srgrimes ah->ar_pro = htons(ETHERTYPE_IP); 3211541Srgrimes ah->ar_hln = ifp->if_addrlen; /* hardware address length */ 3221541Srgrimes ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ 3231541Srgrimes ah->ar_op = htons(ARPOP_REQUEST); 3241541Srgrimes bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln); 3251541Srgrimes bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln); 3261541Srgrimes bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln); 3271541Srgrimes sa.sa_family = AF_ARP; 32824448Speter sa.sa_len = 2; 32924448Speter m->m_flags |= M_BCAST; 33024448Speter (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0); 33124448Speter 33224448Speter return; 33324448Speter} 33424448Speter 33524448Speter/* 33624448Speter * Resolve an IP address into an ethernet address. If success, 33724448Speter * desten is filled in. If there is no entry in arptab, 33824448Speter * set one up and broadcast a request for the IP address. 33924448Speter * Hold onto this mbuf and resend it once the address 34024448Speter * is finally resolved. A return value of 1 indicates 34124448Speter * that desten has been filled in and the packet should be sent 34224448Speter * normally; a 0 return indicates that the packet has been 34324448Speter * taken over here, either now or for later transmission. 34424448Speter * 3451541Srgrimes * NEW COMMENT 34624448Speter * Resolve an IP address into an ethernet address. 34717994Sache * On input: 34824448Speter * ifp is the interface we use 34917994Sache * dst is the next hop, 35024448Speter * rt0 is the route to the final destination (possibly useless) 35124448Speter * m is the mbuf 35224448Speter * desten is where we want the address. 3538162Sache * 3541541Srgrimes * On success, desten is filled in and the function returns 0; 35524448Speter * If the packet must be held pending resolution, we return EWOULDBLOCK 35624448Speter * On other errors, we return the corresponding error code. 3571541Srgrimes */ 35824448Speterint 35924448Speterarpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, 3601541Srgrimes struct sockaddr *dst, u_char *desten) 36117994Sache{ 36224448Speter struct llinfo_arp *la = 0; 36324448Speter struct sockaddr_dl *sdl; 36417994Sache int error; 36524448Speter struct rtentry *rt; 36617994Sache 36724448Speter error = rt_check(&rt, &rt0, dst); 36824448Speter if (error) { 36924448Speter m_freem(m); 37024448Speter return error; 37124448Speter } 37224448Speter 37324448Speter if (m->m_flags & M_BCAST) { /* broadcast */ 37424448Speter (void)memcpy(desten, ifp->if_broadcastaddr, ifp->if_addrlen); 37524448Speter return (0); 37624448Speter } 37724448Speter if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) {/* multicast */ 37824448Speter ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); 37924448Speter return (0); 38024448Speter } 38124448Speter if (rt) 38224448Speter la = (struct llinfo_arp *)rt->rt_llinfo; 38324448Speter if (la == 0) { 38424448Speter la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0); 38524448Speter if (la) 38624448Speter rt = la->la_rt; 38724448Speter } 38824448Speter if (la == 0 || rt == 0) { 38924448Speter log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s%s%s\n", 39024448Speter inet_ntoa(SIN(dst)->sin_addr), la ? "la" : "", 39124448Speter rt ? "rt" : ""); 39224448Speter m_freem(m); 3938141Sache return (EINVAL); /* XXX */ 39424448Speter } 39524448Speter sdl = SDL(rt->rt_gateway); 39624448Speter /* 39724448Speter * Check the address family and length is valid, the address 39824448Speter * is resolved; otherwise, try to resolve. 39924448Speter */ 40024448Speter if ((rt->rt_expire == 0 || rt->rt_expire > time_second) && 40124448Speter sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { 40224448Speter /* 40324448Speter * If entry has an expiry time and it is approaching, 4041541Srgrimes * see if we need to send an ARP request within this 4051541Srgrimes * arpt_down interval. 4061541Srgrimes */ 40712221Sbde if ((rt->rt_expire != 0) && 4081541Srgrimes (time_second + la->la_preempt > rt->rt_expire)) { 4091541Srgrimes arprequest(ifp, 4101541Srgrimes &SIN(rt->rt_ifa->ifa_addr)->sin_addr, 41112221Sbde &SIN(dst)->sin_addr, 4121541Srgrimes IF_LLADDR(ifp)); 4131549Srgrimes la->la_preempt--; 4141541Srgrimes } 4151541Srgrimes 4161541Srgrimes bcopy(LLADDR(sdl), desten, sdl->sdl_alen); 4171541Srgrimes return (0); 4181541Srgrimes } 4191541Srgrimes /* 4201541Srgrimes * If ARP is disabled or static on this interface, stop. 4211541Srgrimes * XXX 4221541Srgrimes * Probably should not allocate empty llinfo struct if we are 4231541Srgrimes * not going to be sending out an arp request. 42424449Speter */ 42524449Speter if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) { 4261541Srgrimes m_freem(m); 4271541Srgrimes return (EINVAL); 4281541Srgrimes } 4291541Srgrimes /* 4301541Srgrimes * There is an arptab entry, but no ethernet address 4311541Srgrimes * response yet. Replace the held mbuf with this 43224449Speter * latest one. 43324449Speter */ 43424449Speter if (la->la_hold) 43524449Speter m_freem(la->la_hold); 43624449Speter la->la_hold = m; 4371541Srgrimes if (rt->rt_expire) { 4381541Srgrimes RT_LOCK(rt); 4391541Srgrimes rt->rt_flags &= ~RTF_REJECT; 44012221Sbde if (la->la_asked == 0 || rt->rt_expire != time_second) { 4411541Srgrimes rt->rt_expire = time_second; 4421541Srgrimes if (la->la_asked++ < arp_maxtries) { 4431541Srgrimes arprequest(ifp, 44412221Sbde &SIN(rt->rt_ifa->ifa_addr)->sin_addr, 4451541Srgrimes &SIN(dst)->sin_addr, 4461549Srgrimes IF_LLADDR(ifp)); 4471541Srgrimes } else { 4481541Srgrimes rt->rt_flags |= RTF_REJECT; 4491541Srgrimes rt->rt_expire += arpt_down; 4501541Srgrimes la->la_asked = 0; 4511541Srgrimes la->la_preempt = arp_maxtries; 4521541Srgrimes } 4531541Srgrimes 4541541Srgrimes } 4551541Srgrimes RT_UNLOCK(rt); 45624448Speter } 45724448Speter return (EWOULDBLOCK); 45824448Speter} 45924448Speter 46024448Speter/* 46124448Speter * Common length and type checks are done here, 46224448Speter * then the protocol-specific routine is called. 46324448Speter */ 46424448Speterstatic void 46524448Speterarpintr(struct mbuf *m) 46624448Speter{ 4671541Srgrimes struct arphdr *ar; 46824448Speter 46917994Sache if (!arpinit_done) { 47024448Speter /* NB: this race should not matter */ 47117994Sache arpinit_done = 1; 47224448Speter callout_reset(&arp_callout, hz, arptimer, NULL); 47324448Speter } 47424448Speter if (m->m_len < sizeof(struct arphdr) && 4758162Sache ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) { 4761541Srgrimes log(LOG_ERR, "arp: runt packet -- m_pullup failed\n"); 47724448Speter return; 47817994Sache } 47924448Speter ar = mtod(m, struct arphdr *); 48024448Speter 48124448Speter if (ntohs(ar->ar_hrd) != ARPHRD_ETHER && 48224448Speter ntohs(ar->ar_hrd) != ARPHRD_IEEE802 && 48324448Speter ntohs(ar->ar_hrd) != ARPHRD_ARCNET) { 48424448Speter log(LOG_ERR, "arp: unknown hardware address format (0x%2D)\n", 48524448Speter (unsigned char *)&ar->ar_hrd, ""); 48617994Sache m_freem(m); 48724448Speter return; 48824448Speter } 48924448Speter 49024448Speter if (m->m_len < arphdr_len(ar)) { 49124448Speter if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { 49224448Speter log(LOG_ERR, "arp: runt packet\n"); 49324448Speter m_freem(m); 49424448Speter return; 49524448Speter } 49624448Speter ar = mtod(m, struct arphdr *); 49724448Speter } 49824448Speter 49924448Speter switch (ntohs(ar->ar_pro)) { 50024448Speter#ifdef INET 50124448Speter case ETHERTYPE_IP: 50224448Speter in_arpinput(m); 50324448Speter return; 50424448Speter#endif 50524448Speter } 50624448Speter m_freem(m); 50724448Speter} 5088141Sache 50924448Speter#ifdef INET 51024448Speter/* 51124448Speter * ARP for Internet protocols on 10 Mb/s Ethernet. 51224448Speter * Algorithm is that given in RFC 826. 51324448Speter * In addition, a sanity check is performed on the sender 51424448Speter * protocol address, to catch impersonators. 51524448Speter * We no longer handle negotiations for use of trailer protocol: 51624448Speter * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent 51724448Speter * along with IP replies if we wanted trailers sent to us, 5181541Srgrimes * and also sent them in response to IP replies. 5191541Srgrimes * This allowed either end to announce the desire to receive 5201541Srgrimes * trailer packets. 52112221Sbde * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, 5221541Srgrimes * but formerly didn't normally send requests. 5231541Srgrimes */ 5241541Srgrimesstatic int log_arp_wrong_iface = 1; 52512221Sbdestatic int log_arp_movements = 1; 5261541Srgrimes 5271549SrgrimesSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW, 5281541Srgrimes &log_arp_wrong_iface, 0, 5291541Srgrimes "log arp packets arriving on the wrong interface"); 5301541SrgrimesSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_movements, CTLFLAG_RW, 5311541Srgrimes &log_arp_movements, 0, 5321541Srgrimes "log arp replies from MACs different than the one in the cache"); 5331541Srgrimes 5341541Srgrimes 5351541Srgrimesstatic void 5361541Srgrimesin_arpinput(m) 5371541Srgrimes struct mbuf *m; 53824449Speter{ 53924449Speter struct arphdr *ah; 5401541Srgrimes struct ifnet *ifp = m->m_pkthdr.rcvif; 5411541Srgrimes struct iso88025_header *th = (struct iso88025_header *)0; 54224449Speter struct iso88025_sockaddr_dl_data *trld; 54324449Speter struct llinfo_arp *la = 0; 54424449Speter struct rtentry *rt; 54524449Speter struct ifaddr *ifa; 54624449Speter struct in_ifaddr *ia; 5471541Srgrimes struct sockaddr_dl *sdl; 5481541Srgrimes struct sockaddr sa; 5491541Srgrimes struct in_addr isaddr, itaddr, myaddr; 55012221Sbde int op, rif_len; 5511541Srgrimes int req_len; 5521541Srgrimes 5531541Srgrimes req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); 5541541Srgrimes if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) { 55512221Sbde log(LOG_ERR, "in_arp: runt packet -- m_pullup failed\n"); 5561541Srgrimes return; 5571549Srgrimes } 5581541Srgrimes 5591541Srgrimes ah = mtod(m, struct arphdr *); 5601541Srgrimes op = ntohs(ah->ar_op); 5611541Srgrimes (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 5621541Srgrimes (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 5631541Srgrimes#ifdef BRIDGE 5641541Srgrimes#define BRIDGE_TEST (do_bridge) 5651541Srgrimes#else 5661541Srgrimes#define BRIDGE_TEST (0) /* cc will optimise the test away */ 5673098Sphk#endif 5681541Srgrimes /* 56912063Sdg * For a bridge, we want to check the address irrespective 57024447Speter * of the receive interface. (This will change slightly 5711541Srgrimes * when we have clusters of interfaces). 57224447Speter */ 57324447Speter LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) 57424447Speter if ((BRIDGE_TEST || (ia->ia_ifp == ifp)) && 57524447Speter itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) 5761541Srgrimes goto match; 57724447Speter LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) 57824447Speter if ((BRIDGE_TEST || (ia->ia_ifp == ifp)) && 57924447Speter isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) 58024447Speter goto match; 58124447Speter /* 58224447Speter * No match, use the first inet address on the receive interface 58324447Speter * as a dummy address for the rest of the function. 58424447Speter */ 58524447Speter TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 58624447Speter if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) { 58724447Speter ia = ifatoia(ifa); 58824447Speter goto match; 58924447Speter } 59024447Speter /* 5911541Srgrimes * If bridging, fall back to using any inet address. 5921541Srgrimes */ 5931541Srgrimes if (!BRIDGE_TEST || 5941541Srgrimes (ia = TAILQ_FIRST(&in_ifaddrhead)) == NULL) { 59512221Sbde m_freem(m); 5961541Srgrimes return; 5979238Sache } 5989238Sachematch: 5991541Srgrimes myaddr = ia->ia_addr.sin_addr; 60012221Sbde if (!bcmp(ar_sha(ah), IF_LLADDR(ifp), ifp->if_addrlen)) { 6011541Srgrimes m_freem(m); /* it's from me, ignore it. */ 6021549Srgrimes return; 6038019Sache } 6041541Srgrimes if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { 6051541Srgrimes log(LOG_ERR, 6061541Srgrimes "arp: link address is broadcast for IP address %s!\n", 6071541Srgrimes inet_ntoa(isaddr)); 6081541Srgrimes m_freem(m); 6099238Sache return; 6108135Sache } 6111541Srgrimes if (isaddr.s_addr == myaddr.s_addr) { 6129238Sache log(LOG_ERR, 6139238Sache "arp: %*D is using my IP address %s!\n", 6149238Sache ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 6159238Sache inet_ntoa(isaddr)); 6168135Sache itaddr = myaddr; 6178135Sache goto reply; 6189238Sache } 61924450Speter if (ifp->if_flags & IFF_STATICARP) 62024450Speter goto reply; 6219238Sache la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0); 62224450Speter if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) { 62324450Speter /* the following is not an error when doing bridging */ 62424450Speter if (!BRIDGE_TEST && rt->rt_ifp != ifp) { 6259238Sache if (log_arp_wrong_iface) 6269238Sache log(LOG_ERR, "arp: %s is on %s but got reply from %*D on %s\n", 6279238Sache inet_ntoa(isaddr), 62824450Speter rt->rt_ifp->if_xname, 6298135Sache ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 63024450Speter ifp->if_xname); 6318111Sache goto reply; 63224450Speter } 63324450Speter if (sdl->sdl_alen && 6348135Sache bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) { 6351541Srgrimes if (rt->rt_expire) { 6361541Srgrimes if (log_arp_movements) 63712221Sbde log(LOG_INFO, "arp: %s moved from %*D to %*D on %s\n", 6381541Srgrimes inet_ntoa(isaddr), 6399238Sache ifp->if_addrlen, (u_char *)LLADDR(sdl), ":", 6409238Sache ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 6411541Srgrimes ifp->if_xname); 64212221Sbde } else { 6431541Srgrimes log(LOG_ERR, 6441549Srgrimes "arp: %*D attempts to modify permanent entry for %s on %s\n", 6458019Sache ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 6461541Srgrimes inet_ntoa(isaddr), ifp->if_xname); 6471541Srgrimes goto reply; 6481541Srgrimes } 6491541Srgrimes } 6501541Srgrimes /* 6519238Sache * sanity check for the address length. 6528135Sache * XXX this does not work for protocols with variable address 6531541Srgrimes * length. -is 6549238Sache */ 6559238Sache if (sdl->sdl_alen && 6569238Sache sdl->sdl_alen != ah->ar_hln) { 6579238Sache log(LOG_WARNING, 6588135Sache "arp from %*D: new addr len %d, was %d", 6598135Sache ifp->if_addrlen, (u_char *) ar_sha(ah), ":", 6609238Sache ah->ar_hln, sdl->sdl_alen); 66124450Speter } 66224450Speter if (ifp->if_addrlen != ah->ar_hln) { 6639238Sache log(LOG_WARNING, 66424450Speter "arp from %*D: addr len: new %d, i/f %d (ignored)", 66524450Speter ifp->if_addrlen, (u_char *) ar_sha(ah), ":", 66624450Speter ah->ar_hln, ifp->if_addrlen); 6679238Sache goto reply; 66824450Speter } 66924450Speter (void)memcpy(LLADDR(sdl), ar_sha(ah), 67024450Speter sdl->sdl_alen = ah->ar_hln); 6718111Sache /* 67224450Speter * If we receive an arp from a token-ring station over 67324450Speter * a token-ring nic then try to save the source 6748135Sache * routing info. 6751541Srgrimes */ 6761541Srgrimes if (ifp->if_type == IFT_ISO88025) { 67724453Speter th = (struct iso88025_header *)m->m_pkthdr.header; 67824453Speter trld = SDL_ISO88025(sdl); 67924453Speter rif_len = TR_RCF_RIFLEN(th->rcf); 68024453Speter if ((th->iso88025_shost[0] & TR_RII) && 68124453Speter (rif_len > 2)) { 68224453Speter trld->trld_rcf = th->rcf; 68324453Speter trld->trld_rcf ^= htons(TR_RCF_DIR); 68424453Speter memcpy(trld->trld_route, th->rd, rif_len - 2); 68524453Speter trld->trld_rcf &= ~htons(TR_RCF_BCST_MASK); 68624453Speter /* 68724453Speter * Set up source routing information for 68824453Speter * reply packet (XXX) 68924453Speter */ 69024453Speter m->m_data -= rif_len; 69124453Speter m->m_len += rif_len; 69224453Speter m->m_pkthdr.len += rif_len; 69324453Speter } else { 69424453Speter th->iso88025_shost[0] &= ~TR_RII; 69524453Speter trld->trld_rcf = 0; 69624453Speter } 69724453Speter m->m_data -= 8; 69824453Speter m->m_len += 8; 69924453Speter m->m_pkthdr.len += 8; 70024453Speter th->rcf = trld->trld_rcf; 70124453Speter } 7021541Srgrimes RT_LOCK(rt); 7031541Srgrimes if (rt->rt_expire) 7041541Srgrimes rt->rt_expire = time_second + arpt_keep; 7051549Srgrimes rt->rt_flags &= ~RTF_REJECT; 7061541Srgrimes RT_UNLOCK(rt); 7071541Srgrimes la->la_asked = 0; 7081541Srgrimes la->la_preempt = arp_maxtries; 7091541Srgrimes if (la->la_hold) { 7101541Srgrimes (*ifp->if_output)(ifp, la->la_hold, rt_key(rt), rt); 7111541Srgrimes la->la_hold = 0; 7121541Srgrimes } 7131541Srgrimes } 7141541Srgrimesreply: 7151541Srgrimes if (op != ARPOP_REQUEST) { 7161541Srgrimes m_freem(m); 7171541Srgrimes return; 7181541Srgrimes } 7191541Srgrimes if (itaddr.s_addr == myaddr.s_addr) { 7201541Srgrimes /* I am the target */ 7211541Srgrimes (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 7221541Srgrimes (void)memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln); 7231541Srgrimes } else { 7241541Srgrimes la = arplookup(itaddr.s_addr, 0, SIN_PROXY); 7251541Srgrimes if (la == NULL) { 7261549Srgrimes struct sockaddr_in sin; 7271541Srgrimes 7281541Srgrimes if (!arp_proxyall) { 7298011Sbde m_freem(m); 7301541Srgrimes return; 7311541Srgrimes } 7321541Srgrimes 7331541Srgrimes bzero(&sin, sizeof sin); 7341541Srgrimes sin.sin_family = AF_INET; 7351541Srgrimes sin.sin_len = sizeof sin; 7361541Srgrimes sin.sin_addr = itaddr; 7371541Srgrimes 7381541Srgrimes rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); 7391541Srgrimes if (!rt) { 7401541Srgrimes m_freem(m); 7411541Srgrimes return; 7421541Srgrimes } 7431541Srgrimes /* 7441541Srgrimes * Don't send proxies for nodes on the same interface 7451541Srgrimes * as this one came out of, or we'll get into a fight 7461541Srgrimes * over who claims what Ether address. 7471541Srgrimes */ 7481541Srgrimes if (rt->rt_ifp == ifp) { 7491541Srgrimes rtfree(rt); 7501541Srgrimes m_freem(m); 7511541Srgrimes return; 7521541Srgrimes } 7531541Srgrimes (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 7541541Srgrimes (void)memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln); 7551541Srgrimes rtfree(rt); 7561541Srgrimes 7571549Srgrimes /* 7581541Srgrimes * Also check that the node which sent the ARP packet 7591541Srgrimes * is on the the interface we expect it to be on. This 7601541Srgrimes * avoids ARP chaos if an interface is connected to the 7611541Srgrimes * wrong network. 7621541Srgrimes */ 7631541Srgrimes sin.sin_addr = isaddr; 7641541Srgrimes 7651541Srgrimes rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); 7661541Srgrimes if (!rt) { 7671541Srgrimes m_freem(m); 7681541Srgrimes return; 7691541Srgrimes } 7701541Srgrimes if (rt->rt_ifp != ifp) { 7711541Srgrimes log(LOG_INFO, "arp_proxy: ignoring request" 7721541Srgrimes " from %s via %s, expecting %s\n", 7731541Srgrimes inet_ntoa(isaddr), ifp->if_xname, 7741541Srgrimes rt->rt_ifp->if_xname); 7751541Srgrimes rtfree(rt); 7761541Srgrimes m_freem(m); 7771541Srgrimes return; 7781541Srgrimes } 7791541Srgrimes rtfree(rt); 7801541Srgrimes 7811541Srgrimes#ifdef DEBUG_PROXY 7821541Srgrimes printf("arp: proxying for %s\n", 7831541Srgrimes inet_ntoa(itaddr)); 7841541Srgrimes#endif 7851541Srgrimes } else { 7861541Srgrimes rt = la->la_rt; 7871541Srgrimes (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 7881541Srgrimes sdl = SDL(rt->rt_gateway); 7891541Srgrimes (void)memcpy(ar_sha(ah), LLADDR(sdl), ah->ar_hln); 7901541Srgrimes } 7911541Srgrimes } 7921541Srgrimes 7931541Srgrimes (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); 7941541Srgrimes (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 7951541Srgrimes ah->ar_op = htons(ARPOP_REPLY); 7961541Srgrimes ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 7971541Srgrimes m->m_flags &= ~(M_BCAST|M_MCAST); /* never reply by broadcast */ 7981541Srgrimes m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 7991541Srgrimes m->m_pkthdr.len = m->m_len; 8001541Srgrimes sa.sa_family = AF_ARP; 8011541Srgrimes sa.sa_len = 2; 8021541Srgrimes (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0); 8031541Srgrimes return; 8041541Srgrimes} 80512221Sbde#endif 8061541Srgrimes 8071541Srgrimes/* 8081541Srgrimes * Free an arp entry. 8091541Srgrimes */ 81012221Sbdestatic void 8111541Srgrimesarptfree(la) 8121549Srgrimes struct llinfo_arp *la; 8131541Srgrimes{ 8141541Srgrimes struct rtentry *rt = la->la_rt; 8151541Srgrimes struct sockaddr_dl *sdl; 8161541Srgrimes 8171541Srgrimes if (rt == 0) 8181541Srgrimes panic("arptfree"); 81923358Sache if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) && 82023359Sache sdl->sdl_family == AF_LINK) { 8211541Srgrimes sdl->sdl_alen = 0; 8221541Srgrimes la->la_preempt = la->la_asked = 0; 8231541Srgrimes RT_LOCK(rt); /* XXX needed or move higher? */ 8241541Srgrimes rt->rt_flags &= ~RTF_REJECT; 8251541Srgrimes RT_UNLOCK(rt); 8261541Srgrimes return; 8271541Srgrimes } 82812221Sbde rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt), 8291541Srgrimes 0, (struct rtentry **)0); 8301541Srgrimes} 8311541Srgrimes/* 83212221Sbde * Lookup or enter a new address in arptab. 8331541Srgrimes */ 8341549Srgrimesstatic struct llinfo_arp * 8351541Srgrimesarplookup(addr, create, proxy) 8361541Srgrimes u_long addr; 8371541Srgrimes int create, proxy; 8381541Srgrimes{ 8391541Srgrimes struct rtentry *rt; 8401541Srgrimes struct sockaddr_inarp sin; 84123330Sache const char *why = 0; 8421541Srgrimes 8433098Sphk bzero(&sin, sizeof(sin)); 8441541Srgrimes sin.sin_len = sizeof(sin); 84522522Sdavidn sin.sin_family = AF_INET; 84622522Sdavidn sin.sin_addr.s_addr = addr; 8471541Srgrimes if (proxy) 8481541Srgrimes sin.sin_other = SIN_PROXY; 84922522Sdavidn rt = rtalloc1((struct sockaddr *)&sin, create, 0UL); 85022522Sdavidn if (rt == 0) 85123330Sache return (0); 8521541Srgrimes 8531541Srgrimes if (rt->rt_flags & RTF_GATEWAY) 854 why = "host is not on local network"; 855 else if ((rt->rt_flags & RTF_LLINFO) == 0) 856 why = "could not allocate llinfo"; 857 else if (rt->rt_gateway->sa_family != AF_LINK) 858 why = "gateway route is not ours"; 859 860 if (why) { 861#define ISDYNCLONE(_rt) \ 862 (((_rt)->rt_flags & (RTF_STATIC | RTF_WASCLONED)) == RTF_WASCLONED) 863 if (create) 864 log(LOG_DEBUG, "arplookup %s failed: %s\n", 865 inet_ntoa(sin.sin_addr), why); 866 /* 867 * If there are no references to this Layer 2 route, 868 * and it is a cloned route, and not static, and 869 * arplookup() is creating the route, then purge 870 * it from the routing table as it is probably bogus. 871 */ 872 if (rt->rt_refcnt == 1 && ISDYNCLONE(rt)) 873 rtexpunge(rt); 874 RTFREE_LOCKED(rt); 875 return (0); 876#undef ISDYNCLONE 877 } else { 878 RT_REMREF(rt); 879 RT_UNLOCK(rt); 880 return ((struct llinfo_arp *)rt->rt_llinfo); 881 } 882} 883 884void 885arp_ifinit(ifp, ifa) 886 struct ifnet *ifp; 887 struct ifaddr *ifa; 888{ 889 if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) 890 arprequest(ifp, &IA_SIN(ifa)->sin_addr, 891 &IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp)); 892 ifa->ifa_rtrequest = arp_rtrequest; 893 ifa->ifa_flags |= RTF_CLONING; 894} 895 896static void 897arp_init(void) 898{ 899 900 arpintrq.ifq_maxlen = 50; 901 mtx_init(&arpintrq.ifq_mtx, "arp_inq", NULL, MTX_DEF); 902 LIST_INIT(&llinfo_arp); 903 callout_init(&arp_callout, CALLOUT_MPSAFE); 904 netisr_register(NETISR_ARP, arpintr, &arpintrq, NETISR_MPSAFE); 905} 906SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); 907