if_ether.c revision 228571
1139823Simp/*- 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 */ 311541Srgrimes 321541Srgrimes/* 331541Srgrimes * Ethernet address resolution protocol. 341541Srgrimes * TODO: 351541Srgrimes * add "inuse/lock" bit (or ref. count) along with valid bit 361541Srgrimes */ 371541Srgrimes 38172467Ssilby#include <sys/cdefs.h> 39172467Ssilby__FBSDID("$FreeBSD: head/sys/netinet/if_ether.c 228571 2011-12-16 12:16:56Z glebius $"); 40172467Ssilby 4132350Seivind#include "opt_inet.h" 4232350Seivind 431541Srgrimes#include <sys/param.h> 4412693Sphk#include <sys/kernel.h> 4544078Sdfr#include <sys/queue.h> 4612693Sphk#include <sys/sysctl.h> 471541Srgrimes#include <sys/systm.h> 4812693Sphk#include <sys/mbuf.h> 491541Srgrimes#include <sys/malloc.h> 50183014Sjulian#include <sys/proc.h> 5118892Sbde#include <sys/socket.h> 521541Srgrimes#include <sys/syslog.h> 531541Srgrimes 541541Srgrimes#include <net/if.h> 551541Srgrimes#include <net/if_dl.h> 5644165Sjulian#include <net/if_types.h> 578426Swollman#include <net/netisr.h> 5858313Slile#include <net/if_llc.h> 5971963Sjulian#include <net/ethernet.h> 60194739Sbz#include <net/route.h> 61196019Srwatson#include <net/vnet.h> 621541Srgrimes 631541Srgrimes#include <netinet/in.h> 641541Srgrimes#include <netinet/in_var.h> 65186119Sqingli#include <net/if_llatbl.h> 661541Srgrimes#include <netinet/if_ether.h> 67211193Swill#if defined(INET) || defined(INET6) 68211193Swill#include <netinet/ip_carp.h> 69211193Swill#endif 701541Srgrimes 7184931Sfjoe#include <net/if_arc.h> 7244627Sjulian#include <net/iso88025.h> 7344627Sjulian 74163606Srwatson#include <security/mac/mac_framework.h> 75163606Srwatson 761541Srgrimes#define SIN(s) ((struct sockaddr_in *)s) 771541Srgrimes#define SDL(s) ((struct sockaddr_dl *)s) 781541Srgrimes 7944078SdfrSYSCTL_DECL(_net_link_ether); 80227309Sedstatic SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); 81227309Sedstatic SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, ""); 821541Srgrimes 8312693Sphk/* timer values */ 84215701Sdimstatic VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20 85195699Srwatson * minutes */ 86215701Sdimstatic VNET_DEFINE(int, arp_maxtries) = 5; 87207369SbzVNET_DEFINE(int, useloopback) = 1; /* use loopback interface for 88207369Sbz * local traffic */ 89215701Sdimstatic VNET_DEFINE(int, arp_proxyall) = 0; 90215701Sdimstatic VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for 91198111Sqingli * 20 seconds */ 92215207SgnnVNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */ 931541Srgrimes 94215701Sdimstatic VNET_DEFINE(int, arp_maxhold) = 1; 95215207Sgnn 96195727Srwatson#define V_arpt_keep VNET(arpt_keep) 97198111Sqingli#define V_arpt_down VNET(arpt_down) 98195727Srwatson#define V_arp_maxtries VNET(arp_maxtries) 99195727Srwatson#define V_arp_proxyall VNET(arp_proxyall) 100196797Sgnn#define V_arpstat VNET(arpstat) 101215207Sgnn#define V_arp_maxhold VNET(arp_maxhold) 10212693Sphk 103195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, 104195699Srwatson &VNET_NAME(arpt_keep), 0, 105195699Srwatson "ARP entry lifetime in seconds"); 106195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, 107195699Srwatson &VNET_NAME(arp_maxtries), 0, 108183550Szec "ARP resolution attempts before returning error"); 109195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW, 110195699Srwatson &VNET_NAME(useloopback), 0, 111183550Szec "Use the loopback interface for local traffic"); 112195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, 113195699Srwatson &VNET_NAME(arp_proxyall), 0, 114183550Szec "Enable proxy ARP for all suitable requests"); 115215207SgnnSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, wait, CTLFLAG_RW, 116215207Sgnn &VNET_NAME(arpt_down), 0, 117215207Sgnn "Incomplete ARP entry lifetime in seconds"); 118196797SgnnSYSCTL_VNET_STRUCT(_net_link_ether_arp, OID_AUTO, stats, CTLFLAG_RW, 119196797Sgnn &VNET_NAME(arpstat), arpstat, 120196797Sgnn "ARP statistics (struct arpstat, net/if_arp.h)"); 121215207SgnnSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxhold, CTLFLAG_RW, 122215207Sgnn &VNET_NAME(arp_maxhold), 0, 123215207Sgnn "Number of packets to hold per ARP entry"); 12412693Sphk 12592723Salfredstatic void arp_init(void); 126186119Sqinglivoid arprequest(struct ifnet *, 12792723Salfred struct in_addr *, struct in_addr *, u_char *); 128111888Sjlemonstatic void arpintr(struct mbuf *); 12992723Salfredstatic void arptimer(void *); 13032350Seivind#ifdef INET 13192723Salfredstatic void in_arpinput(struct mbuf *); 13232350Seivind#endif 13312693Sphk 134193219Srwatsonstatic const struct netisr_handler arp_nh = { 135193219Srwatson .nh_name = "arp", 136193219Srwatson .nh_handler = arpintr, 137193219Srwatson .nh_proto = NETISR_ARP, 138193219Srwatson .nh_policy = NETISR_POLICY_SOURCE, 139193219Srwatson}; 140193219Srwatson 141186119Sqingli#ifdef AF_INET 1421541Srgrimes/* 143186119Sqingli * called by in_ifscrub to remove entry from the table when 144186119Sqingli * the interface goes away 1451541Srgrimes */ 146186119Sqinglivoid 147186119Sqingliarp_ifscrub(struct ifnet *ifp, uint32_t addr) 1481541Srgrimes{ 149186119Sqingli struct sockaddr_in addr4; 1501541Srgrimes 151186119Sqingli bzero((void *)&addr4, sizeof(addr4)); 152186119Sqingli addr4.sin_len = sizeof(addr4); 153186119Sqingli addr4.sin_family = AF_INET; 154186119Sqingli addr4.sin_addr.s_addr = addr; 155186119Sqingli IF_AFDATA_LOCK(ifp); 156186119Sqingli lla_lookup(LLTABLE(ifp), (LLE_DELETE | LLE_IFADDR), 157186119Sqingli (struct sockaddr *)&addr4); 158186119Sqingli IF_AFDATA_UNLOCK(ifp); 1591541Srgrimes} 160186119Sqingli#endif 1611541Srgrimes 1621541Srgrimes/* 163186119Sqingli * Timeout routine. Age arp_tab entries periodically. 1641541Srgrimes */ 1655196Swollmanstatic void 166186119Sqingliarptimer(void *arg) 1671541Srgrimes{ 168186119Sqingli struct ifnet *ifp; 169210703Sbz struct llentry *lle; 170215207Sgnn int pkts_dropped; 1711541Srgrimes 172210703Sbz KASSERT(arg != NULL, ("%s: arg NULL", __func__)); 173210703Sbz lle = (struct llentry *)arg; 174186119Sqingli ifp = lle->lle_tbl->llt_ifp; 175196797Sgnn CURVNET_SET(ifp->if_vnet); 176186119Sqingli IF_AFDATA_LOCK(ifp); 177186119Sqingli LLE_WLOCK(lle); 178201544Sqingli if (lle->la_flags & LLE_STATIC) 179201544Sqingli LLE_WUNLOCK(lle); 180201544Sqingli else { 181201544Sqingli if (!callout_pending(&lle->la_timer) && 182201544Sqingli callout_active(&lle->la_timer)) { 183206481Sbz callout_stop(&lle->la_timer); 184206481Sbz LLE_REMREF(lle); 185215207Sgnn pkts_dropped = llentry_free(lle); 186215207Sgnn ARPSTAT_ADD(dropped, pkts_dropped); 187201544Sqingli ARPSTAT_INC(timeouts); 188214675Sjhb } else { 189198418Sqingli#ifdef DIAGNOSTIC 190201544Sqingli struct sockaddr *l3addr = L3_ADDR(lle); 191201544Sqingli log(LOG_INFO, 192201544Sqingli "arptimer issue: %p, IPv4 address: \"%s\"\n", lle, 193201544Sqingli inet_ntoa( 194201544Sqingli ((const struct sockaddr_in *)l3addr)->sin_addr)); 195214675Sjhb#endif 196214675Sjhb LLE_WUNLOCK(lle); 197201544Sqingli } 1981541Srgrimes } 199186119Sqingli IF_AFDATA_UNLOCK(ifp); 200196797Sgnn CURVNET_RESTORE(); 2011541Srgrimes} 2021541Srgrimes 2031541Srgrimes/* 2041541Srgrimes * Broadcast an ARP request. Caller specifies: 2051541Srgrimes * - arp header source ip address 2061541Srgrimes * - arp header target ip address 2071541Srgrimes * - arp header source ethernet address 2081541Srgrimes */ 209186119Sqinglivoid 210186119Sqingliarprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip, 211169454Srwatson u_char *enaddr) 2121541Srgrimes{ 213126936Smdodd struct mbuf *m; 214126936Smdodd struct arphdr *ah; 2151541Srgrimes struct sockaddr sa; 2161541Srgrimes 217186119Sqingli if (sip == NULL) { 218186119Sqingli /* XXX don't believe this can happen (or explain why) */ 219186119Sqingli /* 220186119Sqingli * The caller did not supply a source address, try to find 221186119Sqingli * a compatible one among those assigned to this interface. 222186119Sqingli */ 223186119Sqingli struct ifaddr *ifa; 224186119Sqingli 225186119Sqingli TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 226186119Sqingli if (!ifa->ifa_addr || 227186119Sqingli ifa->ifa_addr->sa_family != AF_INET) 228186119Sqingli continue; 229186119Sqingli sip = &SIN(ifa->ifa_addr)->sin_addr; 230186119Sqingli if (0 == ((sip->s_addr ^ tip->s_addr) & 231186119Sqingli SIN(ifa->ifa_netmask)->sin_addr.s_addr) ) 232186119Sqingli break; /* found it. */ 233186119Sqingli } 234186119Sqingli if (sip == NULL) { 235186119Sqingli printf("%s: cannot find matching address\n", __func__); 236186119Sqingli return; 237186119Sqingli } 238186119Sqingli } 239186119Sqingli 240111119Simp if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) 2411541Srgrimes return; 242127261Smdodd m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) + 243127261Smdodd 2*ifp->if_data.ifi_addrlen; 244127277Smdodd m->m_pkthdr.len = m->m_len; 245127277Smdodd MH_ALIGN(m, m->m_len); 246127277Smdodd ah = mtod(m, struct arphdr *); 247127261Smdodd bzero((caddr_t)ah, m->m_len); 248101090Srwatson#ifdef MAC 249173095Srwatson mac_netinet_arp_send(ifp, m); 250101090Srwatson#endif 25184931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); 25284931Sfjoe ah->ar_hln = ifp->if_addrlen; /* hardware address length */ 25384931Sfjoe ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ 25484931Sfjoe ah->ar_op = htons(ARPOP_REQUEST); 255127261Smdodd bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln); 256127261Smdodd bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln); 257127261Smdodd bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln); 258127261Smdodd sa.sa_family = AF_ARP; 259127261Smdodd sa.sa_len = 2; 260127261Smdodd m->m_flags |= M_BCAST; 261191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 262196797Sgnn ARPSTAT_INC(txrequests); 2631541Srgrimes} 2641541Srgrimes 2651541Srgrimes/* 266128636Sluigi * Resolve an IP address into an ethernet address. 267128636Sluigi * On input: 268128636Sluigi * ifp is the interface we use 269175025Sjulian * rt0 is the route to the final destination (possibly useless) 270175025Sjulian * m is the mbuf. May be NULL if we don't have a packet. 271128636Sluigi * dst is the next hop, 272128636Sluigi * desten is where we want the address. 273128636Sluigi * 274128636Sluigi * On success, desten is filled in and the function returns 0; 275128636Sluigi * If the packet must be held pending resolution, we return EWOULDBLOCK 276128636Sluigi * On other errors, we return the corresponding error code. 277175025Sjulian * Note that m_freem() handles NULL. 2781541Srgrimes */ 2791541Srgrimesint 280128636Sluigiarpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, 281186119Sqingli struct sockaddr *dst, u_char *desten, struct llentry **lle) 2821541Srgrimes{ 283186119Sqingli struct llentry *la = 0; 284186200Skmacy u_int flags = 0; 285215207Sgnn struct mbuf *curr = NULL; 286215207Sgnn struct mbuf *next = NULL; 287186119Sqingli int error, renew; 2881541Srgrimes 289186119Sqingli *lle = NULL; 290186119Sqingli if (m != NULL) { 291175025Sjulian if (m->m_flags & M_BCAST) { 292175025Sjulian /* broadcast */ 293175025Sjulian (void)memcpy(desten, 294175025Sjulian ifp->if_broadcastaddr, ifp->if_addrlen); 295175025Sjulian return (0); 296175025Sjulian } 297175025Sjulian if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) { 298175025Sjulian /* multicast */ 299175025Sjulian ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); 300175025Sjulian return (0); 301175025Sjulian } 3021541Srgrimes } 303186119Sqingliretry: 304186200Skmacy IF_AFDATA_RLOCK(ifp); 305186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, dst); 306186200Skmacy IF_AFDATA_RUNLOCK(ifp); 307186200Skmacy if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0) 308186200Skmacy && ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0)) { 309186200Skmacy flags |= (LLE_CREATE | LLE_EXCLUSIVE); 310186200Skmacy IF_AFDATA_WLOCK(ifp); 311186200Skmacy la = lla_lookup(LLTABLE(ifp), flags, dst); 312186200Skmacy IF_AFDATA_WUNLOCK(ifp); 313186200Skmacy } 314148955Sglebius if (la == NULL) { 315186119Sqingli if (flags & LLE_CREATE) 316148955Sglebius log(LOG_DEBUG, 317148955Sglebius "arpresolve: can't allocate llinfo for %s\n", 318148955Sglebius inet_ntoa(SIN(dst)->sin_addr)); 319186119Sqingli m_freem(m); 320186119Sqingli return (EINVAL); 321186119Sqingli } 322149909Sglebius 323186119Sqingli if ((la->la_flags & LLE_VALID) && 324216075Sglebius ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { 325186119Sqingli bcopy(&la->ll_addr, desten, ifp->if_addrlen); 32692802Sorion /* 32792802Sorion * If entry has an expiry time and it is approaching, 328186119Sqingli * see if we need to send an ARP request within this 329186119Sqingli * arpt_down interval. 33092802Sorion */ 331186119Sqingli if (!(la->la_flags & LLE_STATIC) && 332216075Sglebius time_uptime + la->la_preempt > la->la_expire) { 333186119Sqingli arprequest(ifp, NULL, 334186119Sqingli &SIN(dst)->sin_addr, IF_LLADDR(ifp)); 335149909Sglebius 336110544Sorion la->la_preempt--; 337186119Sqingli } 338186119Sqingli 339186119Sqingli *lle = la; 340186119Sqingli error = 0; 341186119Sqingli goto done; 342186119Sqingli } 343186119Sqingli 344186119Sqingli if (la->la_flags & LLE_STATIC) { /* should not happen! */ 345186119Sqingli log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", 346186119Sqingli inet_ntoa(SIN(dst)->sin_addr)); 347186119Sqingli m_freem(m); 348186119Sqingli error = EINVAL; 349186119Sqingli goto done; 350186119Sqingli } 35192802Sorion 352216075Sglebius renew = (la->la_asked == 0 || la->la_expire != time_uptime); 353186119Sqingli if ((renew || m != NULL) && (flags & LLE_EXCLUSIVE) == 0) { 354186119Sqingli flags |= LLE_EXCLUSIVE; 355186119Sqingli LLE_RUNLOCK(la); 356186119Sqingli goto retry; 3571541Srgrimes } 3581541Srgrimes /* 3591541Srgrimes * There is an arptab entry, but no ethernet address 360215207Sgnn * response yet. Add the mbuf to the list, dropping 361215207Sgnn * the oldest packet if we have exceeded the system 362215207Sgnn * setting. 3631541Srgrimes */ 364186119Sqingli if (m != NULL) { 365215207Sgnn if (la->la_numheld >= V_arp_maxhold) { 366215207Sgnn if (la->la_hold != NULL) { 367215207Sgnn next = la->la_hold->m_nextpkt; 368215207Sgnn m_freem(la->la_hold); 369215207Sgnn la->la_hold = next; 370215207Sgnn la->la_numheld--; 371215207Sgnn ARPSTAT_INC(dropped); 372215207Sgnn } 373215207Sgnn } 374196797Sgnn if (la->la_hold != NULL) { 375215207Sgnn curr = la->la_hold; 376215207Sgnn while (curr->m_nextpkt != NULL) 377215207Sgnn curr = curr->m_nextpkt; 378215207Sgnn curr->m_nextpkt = m; 379215207Sgnn } else 380215207Sgnn la->la_hold = m; 381215207Sgnn la->la_numheld++; 382186119Sqingli if (renew == 0 && (flags & LLE_EXCLUSIVE)) { 383186119Sqingli flags &= ~LLE_EXCLUSIVE; 384186119Sqingli LLE_DOWNGRADE(la); 385186119Sqingli } 386186119Sqingli 387174699Skmacy } 388152188Sglebius /* 389152188Sglebius * Return EWOULDBLOCK if we have tried less than arp_maxtries. It 390152188Sglebius * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH 391152188Sglebius * if we have already sent arp_maxtries ARP requests. Retransmit the 392152188Sglebius * ARP request, but not faster than one request per second. 393152188Sglebius */ 394181803Sbz if (la->la_asked < V_arp_maxtries) 395152188Sglebius error = EWOULDBLOCK; /* First request. */ 396152188Sglebius else 397201416Snp error = rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) ? 398201416Snp EHOSTUNREACH : EHOSTDOWN; 399152188Sglebius 400186119Sqingli if (renew) { 401206481Sbz int canceled; 402206481Sbz 403186119Sqingli LLE_ADDREF(la); 404216075Sglebius la->la_expire = time_uptime; 405206481Sbz canceled = callout_reset(&la->la_timer, hz * V_arpt_down, 406206481Sbz arptimer, la); 407206481Sbz if (canceled) 408206481Sbz LLE_REMREF(la); 409166010Smaxim la->la_asked++; 410186119Sqingli LLE_WUNLOCK(la); 411186119Sqingli arprequest(ifp, NULL, &SIN(dst)->sin_addr, 412152188Sglebius IF_LLADDR(ifp)); 413186119Sqingli return (error); 414186119Sqingli } 415186119Sqinglidone: 416186119Sqingli if (flags & LLE_EXCLUSIVE) 417186119Sqingli LLE_WUNLOCK(la); 418186119Sqingli else 419186119Sqingli LLE_RUNLOCK(la); 420152188Sglebius return (error); 4211541Srgrimes} 4221541Srgrimes 4231541Srgrimes/* 4241541Srgrimes * Common length and type checks are done here, 4251541Srgrimes * then the protocol-specific routine is called. 4261541Srgrimes */ 42712693Sphkstatic void 428111888Sjlemonarpintr(struct mbuf *m) 4291541Srgrimes{ 430111888Sjlemon struct arphdr *ar; 4311541Srgrimes 432111888Sjlemon if (m->m_len < sizeof(struct arphdr) && 433111888Sjlemon ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) { 434227785Sglebius log(LOG_NOTICE, "arp: runt packet -- m_pullup failed\n"); 435111888Sjlemon return; 436111888Sjlemon } 437111888Sjlemon ar = mtod(m, struct arphdr *); 4381541Srgrimes 439111888Sjlemon if (ntohs(ar->ar_hrd) != ARPHRD_ETHER && 440111888Sjlemon ntohs(ar->ar_hrd) != ARPHRD_IEEE802 && 441130407Sdfr ntohs(ar->ar_hrd) != ARPHRD_ARCNET && 442219819Sjeff ntohs(ar->ar_hrd) != ARPHRD_IEEE1394 && 443219819Sjeff ntohs(ar->ar_hrd) != ARPHRD_INFINIBAND) { 444227790Sglebius log(LOG_NOTICE, "arp: unknown hardware address format (0x%2D)" 445227790Sglebius " (from %*D to %*D)\n", (unsigned char *)&ar->ar_hrd, "", 446227790Sglebius ETHER_ADDR_LEN, (u_char *)ar_sha(ar), ":", 447227790Sglebius ETHER_ADDR_LEN, (u_char *)ar_tha(ar), ":"); 448111888Sjlemon m_freem(m); 449111888Sjlemon return; 450111888Sjlemon } 4511541Srgrimes 452123768Sru if (m->m_len < arphdr_len(ar)) { 453123765Sru if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { 454227785Sglebius log(LOG_NOTICE, "arp: runt packet\n"); 455123765Sru m_freem(m); 456123765Sru return; 457123765Sru } 458123765Sru ar = mtod(m, struct arphdr *); 459111888Sjlemon } 46057900Srwatson 461196797Sgnn ARPSTAT_INC(received); 462111888Sjlemon switch (ntohs(ar->ar_pro)) { 46332350Seivind#ifdef INET 464111888Sjlemon case ETHERTYPE_IP: 465111888Sjlemon in_arpinput(m); 466111888Sjlemon return; 46732350Seivind#endif 4681541Srgrimes } 469111888Sjlemon m_freem(m); 4701541Srgrimes} 4711541Srgrimes 47232350Seivind#ifdef INET 4731541Srgrimes/* 4741541Srgrimes * ARP for Internet protocols on 10 Mb/s Ethernet. 4751541Srgrimes * Algorithm is that given in RFC 826. 4761541Srgrimes * In addition, a sanity check is performed on the sender 4771541Srgrimes * protocol address, to catch impersonators. 4781541Srgrimes * We no longer handle negotiations for use of trailer protocol: 4791541Srgrimes * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent 4801541Srgrimes * along with IP replies if we wanted trailers sent to us, 4811541Srgrimes * and also sent them in response to IP replies. 4821541Srgrimes * This allowed either end to announce the desire to receive 4831541Srgrimes * trailer packets. 4841541Srgrimes * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, 4851541Srgrimes * but formerly didn't normally send requests. 4861541Srgrimes */ 48770699Salfredstatic int log_arp_wrong_iface = 1; 48882893Salfredstatic int log_arp_movements = 1; 489153513Sglebiusstatic int log_arp_permanent_modify = 1; 49070699Salfred 49170699SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW, 49270699Salfred &log_arp_wrong_iface, 0, 49370699Salfred "log arp packets arriving on the wrong interface"); 49482893SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_movements, CTLFLAG_RW, 49582893Salfred &log_arp_movements, 0, 49682966Salfred "log arp replies from MACs different than the one in the cache"); 497153513SglebiusSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_permanent_modify, CTLFLAG_RW, 498153513Sglebius &log_arp_permanent_modify, 0, 499153513Sglebius "log arp replies from MACs different than the one in the permanent arp entry"); 50070699Salfred 50182893Salfred 5021541Srgrimesstatic void 503169454Srwatsonin_arpinput(struct mbuf *m) 5041541Srgrimes{ 505126936Smdodd struct arphdr *ah; 506126936Smdodd struct ifnet *ifp = m->m_pkthdr.rcvif; 507186119Sqingli struct llentry *la = NULL; 508126936Smdodd struct rtentry *rt; 50984102Sjlemon struct ifaddr *ifa; 51084102Sjlemon struct in_ifaddr *ia; 5111541Srgrimes struct sockaddr sa; 5121541Srgrimes struct in_addr isaddr, itaddr, myaddr; 513142215Sglebius u_int8_t *enaddr = NULL; 514186119Sqingli int op, flags; 51584931Sfjoe int req_len; 516181824Sphilip int bridged = 0, is_bridge = 0; 517228571Sglebius int carped; 518174559Skmacy struct sockaddr_in sin; 519174559Skmacy sin.sin_len = sizeof(struct sockaddr_in); 520174559Skmacy sin.sin_family = AF_INET; 521174703Skmacy sin.sin_addr.s_addr = 0; 522183550Szec 523155018Sthompsa if (ifp->if_bridge) 524146986Sthompsa bridged = 1; 525181824Sphilip if (ifp->if_type == IFT_BRIDGE) 526181824Sphilip is_bridge = 1; 527146986Sthompsa 52884931Sfjoe req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); 52984931Sfjoe if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) { 530227785Sglebius log(LOG_NOTICE, "in_arp: runt packet -- m_pullup failed\n"); 53174851Syar return; 53274851Syar } 53374851Syar 53484931Sfjoe ah = mtod(m, struct arphdr *); 535217315Sgnn /* 536217315Sgnn * ARP is only for IPv4 so we can reject packets with 537217315Sgnn * a protocol length not equal to an IPv4 address. 538217315Sgnn */ 539217315Sgnn if (ah->ar_pln != sizeof(struct in_addr)) { 540227785Sglebius log(LOG_NOTICE, "in_arp: requested protocol length != %zu\n", 541217315Sgnn sizeof(struct in_addr)); 542217315Sgnn return; 543217315Sgnn } 544217315Sgnn 545217315Sgnn if (ETHER_IS_MULTICAST(ar_sha(ah))) { 546227785Sglebius log(LOG_NOTICE, "in_arp: %*D is multicast\n", 547227785Sglebius ifp->if_addrlen, (u_char *)ar_sha(ah), ":"); 548217315Sgnn return; 549217315Sgnn } 550217315Sgnn 55184931Sfjoe op = ntohs(ah->ar_op); 55284931Sfjoe (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 55384931Sfjoe (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 554134991Sglebius 555196797Sgnn if (op == ARPOP_REPLY) 556196797Sgnn ARPSTAT_INC(rxreplies); 557196797Sgnn 55884102Sjlemon /* 55984102Sjlemon * For a bridge, we want to check the address irrespective 56084102Sjlemon * of the receive interface. (This will change slightly 56184102Sjlemon * when we have clusters of interfaces). 56284102Sjlemon */ 563194951Srwatson IN_IFADDR_RLOCK(); 564143314Sglebius LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 565217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 566186119Sqingli ia->ia_ifp == ifp) && 567228571Sglebius itaddr.s_addr == ia->ia_addr.sin_addr.s_addr && 568228571Sglebius (ia->ia_ifa.ifa_carp == NULL || 569228571Sglebius (*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) { 570194820Srwatson ifa_ref(&ia->ia_ifa); 571194951Srwatson IN_IFADDR_RUNLOCK(); 572143314Sglebius goto match; 573194820Srwatson } 574143314Sglebius } 57584102Sjlemon LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) 576217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 577186119Sqingli ia->ia_ifp == ifp) && 578194820Srwatson isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 579194820Srwatson ifa_ref(&ia->ia_ifa); 580194951Srwatson IN_IFADDR_RUNLOCK(); 58184102Sjlemon goto match; 582194820Srwatson } 583181824Sphilip 584181824Sphilip#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ 585181824Sphilip (ia->ia_ifp->if_bridge == ifp->if_softc && \ 586181824Sphilip !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ 587181824Sphilip addr == ia->ia_addr.sin_addr.s_addr) 58884102Sjlemon /* 589181824Sphilip * Check the case when bridge shares its MAC address with 590181824Sphilip * some of its children, so packets are claimed by bridge 591181824Sphilip * itself (bridge_input() does it first), but they are really 592181824Sphilip * meant to be destined to the bridge member. 593181824Sphilip */ 594181824Sphilip if (is_bridge) { 595181824Sphilip LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 596181824Sphilip if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { 597194820Srwatson ifa_ref(&ia->ia_ifa); 598181824Sphilip ifp = ia->ia_ifp; 599194951Srwatson IN_IFADDR_RUNLOCK(); 600181824Sphilip goto match; 601181824Sphilip } 602181824Sphilip } 603181824Sphilip } 604181824Sphilip#undef BDG_MEMBER_MATCHES_ARP 605194951Srwatson IN_IFADDR_RUNLOCK(); 606181824Sphilip 607181824Sphilip /* 60885223Sjlemon * No match, use the first inet address on the receive interface 60984102Sjlemon * as a dummy address for the rest of the function. 61084102Sjlemon */ 611194820Srwatson IF_ADDR_LOCK(ifp); 61285223Sjlemon TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 613160038Syar if (ifa->ifa_addr->sa_family == AF_INET) { 61485466Sjlemon ia = ifatoia(ifa); 615194820Srwatson ifa_ref(ifa); 616194837Srwatson IF_ADDR_UNLOCK(ifp); 61785466Sjlemon goto match; 61885466Sjlemon } 619194820Srwatson IF_ADDR_UNLOCK(ifp); 620194820Srwatson 62185466Sjlemon /* 62285466Sjlemon * If bridging, fall back to using any inet address. 62385466Sjlemon */ 624194951Srwatson IN_IFADDR_RLOCK(); 625194951Srwatson if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) { 626194951Srwatson IN_IFADDR_RUNLOCK(); 627128645Sluigi goto drop; 628194951Srwatson } 629194820Srwatson ifa_ref(&ia->ia_ifa); 630194951Srwatson IN_IFADDR_RUNLOCK(); 63184102Sjlemonmatch: 632142215Sglebius if (!enaddr) 633142215Sglebius enaddr = (u_int8_t *)IF_LLADDR(ifp); 634228571Sglebius carped = (ia->ia_ifa.ifa_carp != NULL); 63584102Sjlemon myaddr = ia->ia_addr.sin_addr; 636194820Srwatson ifa_free(&ia->ia_ifa); 637142215Sglebius if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) 638128645Sluigi goto drop; /* it's from me, ignore it. */ 63984931Sfjoe if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { 640227785Sglebius log(LOG_NOTICE, 64184931Sfjoe "arp: link address is broadcast for IP address %s!\n", 6427088Swollman inet_ntoa(isaddr)); 643128645Sluigi goto drop; 6441541Srgrimes } 645136441Srwatson /* 646136441Srwatson * Warn if another host is using the same IP address, but only if the 647136441Srwatson * IP address isn't 0.0.0.0, which is used for DHCP only, in which 648136441Srwatson * case we suppress the warning to avoid false positive complaints of 649136441Srwatson * potential misconfiguration. 650136441Srwatson */ 651228571Sglebius if (!bridged && !carped && isaddr.s_addr == myaddr.s_addr && 652228571Sglebius myaddr.s_addr != 0) { 653228571Sglebius log(LOG_ERR, "arp: %*D is using my IP address %s on %s!\n", 65484931Sfjoe ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 655174256Syar inet_ntoa(isaddr), ifp->if_xname); 6561541Srgrimes itaddr = myaddr; 657196797Sgnn ARPSTAT_INC(dupips); 6581541Srgrimes goto reply; 6591541Srgrimes } 660120626Sru if (ifp->if_flags & IFF_STATICARP) 661120626Sru goto reply; 662148955Sglebius 663186119Sqingli bzero(&sin, sizeof(sin)); 664186119Sqingli sin.sin_len = sizeof(struct sockaddr_in); 665186119Sqingli sin.sin_family = AF_INET; 666186119Sqingli sin.sin_addr = isaddr; 667186119Sqingli flags = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0; 668186119Sqingli flags |= LLE_EXCLUSIVE; 669186119Sqingli IF_AFDATA_LOCK(ifp); 670186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin); 671186119Sqingli IF_AFDATA_UNLOCK(ifp); 672186119Sqingli if (la != NULL) { 673186119Sqingli /* the following is not an error when doing bridging */ 674228571Sglebius if (!bridged && la->lle_tbl->llt_ifp != ifp) { 675186119Sqingli if (log_arp_wrong_iface) 676227785Sglebius log(LOG_WARNING, "arp: %s is on %s " 677186119Sqingli "but got reply from %*D on %s\n", 678186119Sqingli inet_ntoa(isaddr), 679186119Sqingli la->lle_tbl->llt_ifp->if_xname, 680186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 681186119Sqingli ifp->if_xname); 682196738Sbz LLE_WUNLOCK(la); 683186119Sqingli goto reply; 684186119Sqingli } 685186119Sqingli if ((la->la_flags & LLE_VALID) && 686186119Sqingli bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { 687186119Sqingli if (la->la_flags & LLE_STATIC) { 688196738Sbz LLE_WUNLOCK(la); 689223840Sae if (log_arp_permanent_modify) 690223840Sae log(LOG_ERR, 691223840Sae "arp: %*D attempts to modify " 692223840Sae "permanent entry for %s on %s\n", 693223840Sae ifp->if_addrlen, 694223840Sae (u_char *)ar_sha(ah), ":", 695223840Sae inet_ntoa(isaddr), ifp->if_xname); 696186119Sqingli goto reply; 697178888Sjulian } 698186119Sqingli if (log_arp_movements) { 699186119Sqingli log(LOG_INFO, "arp: %s moved from %*D " 700186119Sqingli "to %*D on %s\n", 701186119Sqingli inet_ntoa(isaddr), 702186119Sqingli ifp->if_addrlen, 703186119Sqingli (u_char *)&la->ll_addr, ":", 704186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 705186119Sqingli ifp->if_xname); 706178888Sjulian } 707178888Sjulian } 708186119Sqingli 709186119Sqingli if (ifp->if_addrlen != ah->ar_hln) { 710196738Sbz LLE_WUNLOCK(la); 711227785Sglebius log(LOG_WARNING, "arp from %*D: addr len: new %d, " 712227785Sglebius "i/f %d (ignored)\n", ifp->if_addrlen, 713227785Sglebius (u_char *) ar_sha(ah), ":", ah->ar_hln, 714227785Sglebius ifp->if_addrlen); 715217315Sgnn goto drop; 716178888Sjulian } 717186119Sqingli (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); 718186119Sqingli la->la_flags |= LLE_VALID; 719178888Sjulian 720196995Snp EVENTHANDLER_INVOKE(arp_update_event, la); 721196995Snp 722186119Sqingli if (!(la->la_flags & LLE_STATIC)) { 723206481Sbz int canceled; 724206481Sbz 725206481Sbz LLE_ADDREF(la); 726216075Sglebius la->la_expire = time_uptime + V_arpt_keep; 727206481Sbz canceled = callout_reset(&la->la_timer, 728206481Sbz hz * V_arpt_keep, arptimer, la); 729206481Sbz if (canceled) 730206481Sbz LLE_REMREF(la); 73139389Sfenner } 732178888Sjulian la->la_asked = 0; 733181803Sbz la->la_preempt = V_arp_maxtries; 734215207Sgnn /* 735215207Sgnn * The packets are all freed within the call to the output 736215207Sgnn * routine. 737215207Sgnn * 738215207Sgnn * NB: The lock MUST be released before the call to the 739215207Sgnn * output routine. 740215207Sgnn */ 741215207Sgnn if (la->la_hold != NULL) { 742215207Sgnn struct mbuf *m_hold, *m_hold_next; 743215207Sgnn 744217113Sgnn m_hold = la->la_hold; 745217113Sgnn la->la_hold = NULL; 746217113Sgnn la->la_numheld = 0; 747186119Sqingli memcpy(&sa, L3_ADDR(la), sizeof(sa)); 748215207Sgnn LLE_WUNLOCK(la); 749217121Sgnn for (; m_hold != NULL; m_hold = m_hold_next) { 750215207Sgnn m_hold_next = m_hold->m_nextpkt; 751215207Sgnn m_hold->m_nextpkt = NULL; 752215207Sgnn (*ifp->if_output)(ifp, m_hold, &sa, NULL); 753215207Sgnn } 754215207Sgnn } else 755215207Sgnn LLE_WUNLOCK(la); 756223261Sbz } 757178888Sjulianreply: 758128645Sluigi if (op != ARPOP_REQUEST) 759128645Sluigi goto drop; 760196797Sgnn ARPSTAT_INC(rxrequests); 761186119Sqingli 7621541Srgrimes if (itaddr.s_addr == myaddr.s_addr) { 763178888Sjulian /* Shortcut.. the receiving interface is the target. */ 76484931Sfjoe (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 765142215Sglebius (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 7661541Srgrimes } else { 767186317Sqingli struct llentry *lle = NULL; 7683282Swollman 769186317Sqingli sin.sin_addr = itaddr; 770197225Sqingli IF_AFDATA_LOCK(ifp); 771197225Sqingli lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin); 772197225Sqingli IF_AFDATA_UNLOCK(ifp); 773186317Sqingli 774197225Sqingli if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { 775186317Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 776186317Sqingli (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); 777186317Sqingli LLE_RUNLOCK(lle); 778197225Sqingli } else { 77963080Sdwmalone 780197225Sqingli if (lle != NULL) 781197225Sqingli LLE_RUNLOCK(lle); 782186317Sqingli 783197225Sqingli if (!V_arp_proxyall) 784197225Sqingli goto drop; 785197225Sqingli 786197225Sqingli sin.sin_addr = itaddr; 787197225Sqingli /* XXX MRT use table 0 for arp reply */ 788197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 789197225Sqingli if (!rt) 790197225Sqingli goto drop; 791197225Sqingli 792197225Sqingli /* 793197225Sqingli * Don't send proxies for nodes on the same interface 794197225Sqingli * as this one came out of, or we'll get into a fight 795197225Sqingli * over who claims what Ether address. 796197225Sqingli */ 797197225Sqingli if (!rt->rt_ifp || rt->rt_ifp == ifp) { 798197225Sqingli RTFREE_LOCKED(rt); 799197225Sqingli goto drop; 800197225Sqingli } 801185713Scsjp RTFREE_LOCKED(rt); 80263080Sdwmalone 803197225Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 804197225Sqingli (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 805197225Sqingli 806197225Sqingli /* 807197225Sqingli * Also check that the node which sent the ARP packet 808218909Sbrucec * is on the interface we expect it to be on. This 809197225Sqingli * avoids ARP chaos if an interface is connected to the 810197225Sqingli * wrong network. 811197225Sqingli */ 812197225Sqingli sin.sin_addr = isaddr; 813197225Sqingli 814197225Sqingli /* XXX MRT use table 0 for arp checks */ 815197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 816197225Sqingli if (!rt) 817197225Sqingli goto drop; 818197225Sqingli if (rt->rt_ifp != ifp) { 819197225Sqingli log(LOG_INFO, "arp_proxy: ignoring request" 820197225Sqingli " from %s via %s, expecting %s\n", 821197225Sqingli inet_ntoa(isaddr), ifp->if_xname, 822197225Sqingli rt->rt_ifp->if_xname); 823197225Sqingli RTFREE_LOCKED(rt); 824197225Sqingli goto drop; 825197225Sqingli } 826197225Sqingli RTFREE_LOCKED(rt); 827197225Sqingli 8284069Swollman#ifdef DEBUG_PROXY 829197225Sqingli printf("arp: proxying for %s\n", 830197225Sqingli inet_ntoa(itaddr)); 8314069Swollman#endif 832197225Sqingli } 8331541Srgrimes } 8341541Srgrimes 835166436Sbms if (itaddr.s_addr == myaddr.s_addr && 836166436Sbms IN_LINKLOCAL(ntohl(itaddr.s_addr))) { 837166436Sbms /* RFC 3927 link-local IPv4; always reply by broadcast. */ 838166436Sbms#ifdef DEBUG_LINKLOCAL 839166436Sbms printf("arp: sending reply for link-local addr %s\n", 840166436Sbms inet_ntoa(itaddr)); 841166436Sbms#endif 842166436Sbms m->m_flags |= M_BCAST; 843166436Sbms m->m_flags &= ~M_MCAST; 844166436Sbms } else { 845166436Sbms /* default behaviour; never reply by broadcast. */ 846166436Sbms m->m_flags &= ~(M_BCAST|M_MCAST); 847166436Sbms } 84884931Sfjoe (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); 84984931Sfjoe (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 85084931Sfjoe ah->ar_op = htons(ARPOP_REPLY); 85184931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 852127261Smdodd m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 853127261Smdodd m->m_pkthdr.len = m->m_len; 854223753Sae m->m_pkthdr.rcvif = NULL; 855127261Smdodd sa.sa_family = AF_ARP; 856127261Smdodd sa.sa_len = 2; 857191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 858196797Sgnn ARPSTAT_INC(txreplies); 8591541Srgrimes return; 860128645Sluigi 861128645Sluigidrop: 862128645Sluigi m_freem(m); 8631541Srgrimes} 86432350Seivind#endif 8651541Srgrimes 8665195Swollmanvoid 867169454Srwatsonarp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) 8685195Swollman{ 869186119Sqingli struct llentry *lle; 870186119Sqingli 871228571Sglebius if (ifa->ifa_carp != NULL) 872228571Sglebius return; 873228571Sglebius 874186411Sqingli if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) { 87584931Sfjoe arprequest(ifp, &IA_SIN(ifa)->sin_addr, 87684931Sfjoe &IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp)); 877186411Sqingli /* 878186411Sqingli * interface address is considered static entry 879186411Sqingli * because the output of the arp utility shows 880186411Sqingli * that L2 entry as permanent 881186411Sqingli */ 882186411Sqingli IF_AFDATA_LOCK(ifp); 883186411Sqingli lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC), 884186411Sqingli (struct sockaddr *)IA_SIN(ifa)); 885186411Sqingli IF_AFDATA_UNLOCK(ifp); 886186411Sqingli if (lle == NULL) 887186411Sqingli log(LOG_INFO, "arp_ifinit: cannot create arp " 888186411Sqingli "entry for interface address\n"); 889186411Sqingli else 890186411Sqingli LLE_RUNLOCK(lle); 891186411Sqingli } 892186119Sqingli ifa->ifa_rtrequest = NULL; 8935195Swollman} 89469152Sjlemon 895142215Sglebiusvoid 896169454Srwatsonarp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr) 897142215Sglebius{ 898142215Sglebius if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) 899142215Sglebius arprequest(ifp, &IA_SIN(ifa)->sin_addr, 900142215Sglebius &IA_SIN(ifa)->sin_addr, enaddr); 901186119Sqingli ifa->ifa_rtrequest = NULL; 902142215Sglebius} 903142215Sglebius 904190787Szecstatic void 905190787Szecarp_init(void) 906190787Szec{ 907190787Szec 908193219Srwatson netisr_register(&arp_nh); 90969152Sjlemon} 91069152SjlemonSYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); 911