if_ether.c revision 217113
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 217113 2011-01-07 18:14:58Z gnn $"); 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); 8012942SwollmanSYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); 81196797SgnnSYSCTL_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 142186119Sqinglivoid arp_ifscrub(struct ifnet *ifp, uint32_t addr); 143186119Sqingli 1441541Srgrimes/* 145186119Sqingli * called by in_ifscrub to remove entry from the table when 146186119Sqingli * the interface goes away 1471541Srgrimes */ 148186119Sqinglivoid 149186119Sqingliarp_ifscrub(struct ifnet *ifp, uint32_t addr) 1501541Srgrimes{ 151186119Sqingli struct sockaddr_in addr4; 1521541Srgrimes 153186119Sqingli bzero((void *)&addr4, sizeof(addr4)); 154186119Sqingli addr4.sin_len = sizeof(addr4); 155186119Sqingli addr4.sin_family = AF_INET; 156186119Sqingli addr4.sin_addr.s_addr = addr; 157186119Sqingli IF_AFDATA_LOCK(ifp); 158186119Sqingli lla_lookup(LLTABLE(ifp), (LLE_DELETE | LLE_IFADDR), 159186119Sqingli (struct sockaddr *)&addr4); 160186119Sqingli IF_AFDATA_UNLOCK(ifp); 1611541Srgrimes} 162186119Sqingli#endif 1631541Srgrimes 1641541Srgrimes/* 165186119Sqingli * Timeout routine. Age arp_tab entries periodically. 1661541Srgrimes */ 1675196Swollmanstatic void 168186119Sqingliarptimer(void *arg) 1691541Srgrimes{ 170186119Sqingli struct ifnet *ifp; 171210703Sbz struct llentry *lle; 172215207Sgnn int pkts_dropped; 1731541Srgrimes 174210703Sbz KASSERT(arg != NULL, ("%s: arg NULL", __func__)); 175210703Sbz lle = (struct llentry *)arg; 176186119Sqingli ifp = lle->lle_tbl->llt_ifp; 177196797Sgnn CURVNET_SET(ifp->if_vnet); 178186119Sqingli IF_AFDATA_LOCK(ifp); 179186119Sqingli LLE_WLOCK(lle); 180201544Sqingli if (lle->la_flags & LLE_STATIC) 181201544Sqingli LLE_WUNLOCK(lle); 182201544Sqingli else { 183201544Sqingli if (!callout_pending(&lle->la_timer) && 184201544Sqingli callout_active(&lle->la_timer)) { 185206481Sbz callout_stop(&lle->la_timer); 186206481Sbz LLE_REMREF(lle); 187215207Sgnn pkts_dropped = llentry_free(lle); 188215207Sgnn ARPSTAT_ADD(dropped, pkts_dropped); 189201544Sqingli ARPSTAT_INC(timeouts); 190214675Sjhb } else { 191198418Sqingli#ifdef DIAGNOSTIC 192201544Sqingli struct sockaddr *l3addr = L3_ADDR(lle); 193201544Sqingli log(LOG_INFO, 194201544Sqingli "arptimer issue: %p, IPv4 address: \"%s\"\n", lle, 195201544Sqingli inet_ntoa( 196201544Sqingli ((const struct sockaddr_in *)l3addr)->sin_addr)); 197214675Sjhb#endif 198214675Sjhb LLE_WUNLOCK(lle); 199201544Sqingli } 2001541Srgrimes } 201186119Sqingli IF_AFDATA_UNLOCK(ifp); 202196797Sgnn CURVNET_RESTORE(); 2031541Srgrimes} 2041541Srgrimes 2051541Srgrimes/* 2061541Srgrimes * Broadcast an ARP request. Caller specifies: 2071541Srgrimes * - arp header source ip address 2081541Srgrimes * - arp header target ip address 2091541Srgrimes * - arp header source ethernet address 2101541Srgrimes */ 211186119Sqinglivoid 212186119Sqingliarprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip, 213169454Srwatson u_char *enaddr) 2141541Srgrimes{ 215126936Smdodd struct mbuf *m; 216126936Smdodd struct arphdr *ah; 2171541Srgrimes struct sockaddr sa; 2181541Srgrimes 219186119Sqingli if (sip == NULL) { 220186119Sqingli /* XXX don't believe this can happen (or explain why) */ 221186119Sqingli /* 222186119Sqingli * The caller did not supply a source address, try to find 223186119Sqingli * a compatible one among those assigned to this interface. 224186119Sqingli */ 225186119Sqingli struct ifaddr *ifa; 226186119Sqingli 227186119Sqingli TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 228186119Sqingli if (!ifa->ifa_addr || 229186119Sqingli ifa->ifa_addr->sa_family != AF_INET) 230186119Sqingli continue; 231186119Sqingli sip = &SIN(ifa->ifa_addr)->sin_addr; 232186119Sqingli if (0 == ((sip->s_addr ^ tip->s_addr) & 233186119Sqingli SIN(ifa->ifa_netmask)->sin_addr.s_addr) ) 234186119Sqingli break; /* found it. */ 235186119Sqingli } 236186119Sqingli if (sip == NULL) { 237186119Sqingli printf("%s: cannot find matching address\n", __func__); 238186119Sqingli return; 239186119Sqingli } 240186119Sqingli } 241186119Sqingli 242111119Simp if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) 2431541Srgrimes return; 244127261Smdodd m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) + 245127261Smdodd 2*ifp->if_data.ifi_addrlen; 246127277Smdodd m->m_pkthdr.len = m->m_len; 247127277Smdodd MH_ALIGN(m, m->m_len); 248127277Smdodd ah = mtod(m, struct arphdr *); 249127261Smdodd bzero((caddr_t)ah, m->m_len); 250101090Srwatson#ifdef MAC 251173095Srwatson mac_netinet_arp_send(ifp, m); 252101090Srwatson#endif 25384931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); 25484931Sfjoe ah->ar_hln = ifp->if_addrlen; /* hardware address length */ 25584931Sfjoe ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ 25684931Sfjoe ah->ar_op = htons(ARPOP_REQUEST); 257127261Smdodd bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln); 258127261Smdodd bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln); 259127261Smdodd bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln); 260127261Smdodd sa.sa_family = AF_ARP; 261127261Smdodd sa.sa_len = 2; 262127261Smdodd m->m_flags |= M_BCAST; 263191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 264196797Sgnn ARPSTAT_INC(txrequests); 2651541Srgrimes} 2661541Srgrimes 2671541Srgrimes/* 268128636Sluigi * Resolve an IP address into an ethernet address. 269128636Sluigi * On input: 270128636Sluigi * ifp is the interface we use 271175025Sjulian * rt0 is the route to the final destination (possibly useless) 272175025Sjulian * m is the mbuf. May be NULL if we don't have a packet. 273128636Sluigi * dst is the next hop, 274128636Sluigi * desten is where we want the address. 275128636Sluigi * 276128636Sluigi * On success, desten is filled in and the function returns 0; 277128636Sluigi * If the packet must be held pending resolution, we return EWOULDBLOCK 278128636Sluigi * On other errors, we return the corresponding error code. 279175025Sjulian * Note that m_freem() handles NULL. 2801541Srgrimes */ 2811541Srgrimesint 282128636Sluigiarpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, 283186119Sqingli struct sockaddr *dst, u_char *desten, struct llentry **lle) 2841541Srgrimes{ 285186119Sqingli struct llentry *la = 0; 286186200Skmacy u_int flags = 0; 287215207Sgnn struct mbuf *curr = NULL; 288215207Sgnn struct mbuf *next = NULL; 289186119Sqingli int error, renew; 2901541Srgrimes 291186119Sqingli *lle = NULL; 292186119Sqingli if (m != NULL) { 293175025Sjulian if (m->m_flags & M_BCAST) { 294175025Sjulian /* broadcast */ 295175025Sjulian (void)memcpy(desten, 296175025Sjulian ifp->if_broadcastaddr, ifp->if_addrlen); 297175025Sjulian return (0); 298175025Sjulian } 299175025Sjulian if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) { 300175025Sjulian /* multicast */ 301175025Sjulian ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); 302175025Sjulian return (0); 303175025Sjulian } 3041541Srgrimes } 305186119Sqingliretry: 306186200Skmacy IF_AFDATA_RLOCK(ifp); 307186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, dst); 308186200Skmacy IF_AFDATA_RUNLOCK(ifp); 309186200Skmacy if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0) 310186200Skmacy && ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0)) { 311186200Skmacy flags |= (LLE_CREATE | LLE_EXCLUSIVE); 312186200Skmacy IF_AFDATA_WLOCK(ifp); 313186200Skmacy la = lla_lookup(LLTABLE(ifp), flags, dst); 314186200Skmacy IF_AFDATA_WUNLOCK(ifp); 315186200Skmacy } 316148955Sglebius if (la == NULL) { 317186119Sqingli if (flags & LLE_CREATE) 318148955Sglebius log(LOG_DEBUG, 319148955Sglebius "arpresolve: can't allocate llinfo for %s\n", 320148955Sglebius inet_ntoa(SIN(dst)->sin_addr)); 321186119Sqingli m_freem(m); 322186119Sqingli return (EINVAL); 323186119Sqingli } 324149909Sglebius 325186119Sqingli if ((la->la_flags & LLE_VALID) && 326216075Sglebius ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { 327186119Sqingli bcopy(&la->ll_addr, desten, ifp->if_addrlen); 32892802Sorion /* 32992802Sorion * If entry has an expiry time and it is approaching, 330186119Sqingli * see if we need to send an ARP request within this 331186119Sqingli * arpt_down interval. 33292802Sorion */ 333186119Sqingli if (!(la->la_flags & LLE_STATIC) && 334216075Sglebius time_uptime + la->la_preempt > la->la_expire) { 335186119Sqingli arprequest(ifp, NULL, 336186119Sqingli &SIN(dst)->sin_addr, IF_LLADDR(ifp)); 337149909Sglebius 338110544Sorion la->la_preempt--; 339186119Sqingli } 340186119Sqingli 341186119Sqingli *lle = la; 342186119Sqingli error = 0; 343186119Sqingli goto done; 344186119Sqingli } 345186119Sqingli 346186119Sqingli if (la->la_flags & LLE_STATIC) { /* should not happen! */ 347186119Sqingli log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", 348186119Sqingli inet_ntoa(SIN(dst)->sin_addr)); 349186119Sqingli m_freem(m); 350186119Sqingli error = EINVAL; 351186119Sqingli goto done; 352186119Sqingli } 35392802Sorion 354216075Sglebius renew = (la->la_asked == 0 || la->la_expire != time_uptime); 355186119Sqingli if ((renew || m != NULL) && (flags & LLE_EXCLUSIVE) == 0) { 356186119Sqingli flags |= LLE_EXCLUSIVE; 357186119Sqingli LLE_RUNLOCK(la); 358186119Sqingli goto retry; 3591541Srgrimes } 3601541Srgrimes /* 3611541Srgrimes * There is an arptab entry, but no ethernet address 362215207Sgnn * response yet. Add the mbuf to the list, dropping 363215207Sgnn * the oldest packet if we have exceeded the system 364215207Sgnn * setting. 3651541Srgrimes */ 366186119Sqingli if (m != NULL) { 367215207Sgnn if (la->la_numheld >= V_arp_maxhold) { 368215207Sgnn if (la->la_hold != NULL) { 369215207Sgnn next = la->la_hold->m_nextpkt; 370215207Sgnn m_freem(la->la_hold); 371215207Sgnn la->la_hold = next; 372215207Sgnn la->la_numheld--; 373215207Sgnn ARPSTAT_INC(dropped); 374215207Sgnn } 375215207Sgnn } 376196797Sgnn if (la->la_hold != NULL) { 377215207Sgnn curr = la->la_hold; 378215207Sgnn while (curr->m_nextpkt != NULL) 379215207Sgnn curr = curr->m_nextpkt; 380215207Sgnn curr->m_nextpkt = m; 381215207Sgnn } else 382215207Sgnn la->la_hold = m; 383215207Sgnn la->la_numheld++; 384186119Sqingli if (renew == 0 && (flags & LLE_EXCLUSIVE)) { 385186119Sqingli flags &= ~LLE_EXCLUSIVE; 386186119Sqingli LLE_DOWNGRADE(la); 387186119Sqingli } 388186119Sqingli 389174699Skmacy } 390152188Sglebius /* 391152188Sglebius * Return EWOULDBLOCK if we have tried less than arp_maxtries. It 392152188Sglebius * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH 393152188Sglebius * if we have already sent arp_maxtries ARP requests. Retransmit the 394152188Sglebius * ARP request, but not faster than one request per second. 395152188Sglebius */ 396181803Sbz if (la->la_asked < V_arp_maxtries) 397152188Sglebius error = EWOULDBLOCK; /* First request. */ 398152188Sglebius else 399201416Snp error = rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) ? 400201416Snp EHOSTUNREACH : EHOSTDOWN; 401152188Sglebius 402186119Sqingli if (renew) { 403206481Sbz int canceled; 404206481Sbz 405186119Sqingli LLE_ADDREF(la); 406216075Sglebius la->la_expire = time_uptime; 407206481Sbz canceled = callout_reset(&la->la_timer, hz * V_arpt_down, 408206481Sbz arptimer, la); 409206481Sbz if (canceled) 410206481Sbz LLE_REMREF(la); 411166010Smaxim la->la_asked++; 412186119Sqingli LLE_WUNLOCK(la); 413186119Sqingli arprequest(ifp, NULL, &SIN(dst)->sin_addr, 414152188Sglebius IF_LLADDR(ifp)); 415186119Sqingli return (error); 416186119Sqingli } 417186119Sqinglidone: 418186119Sqingli if (flags & LLE_EXCLUSIVE) 419186119Sqingli LLE_WUNLOCK(la); 420186119Sqingli else 421186119Sqingli LLE_RUNLOCK(la); 422152188Sglebius return (error); 4231541Srgrimes} 4241541Srgrimes 4251541Srgrimes/* 4261541Srgrimes * Common length and type checks are done here, 4271541Srgrimes * then the protocol-specific routine is called. 4281541Srgrimes */ 42912693Sphkstatic void 430111888Sjlemonarpintr(struct mbuf *m) 4311541Srgrimes{ 432111888Sjlemon struct arphdr *ar; 4331541Srgrimes 434111888Sjlemon if (m->m_len < sizeof(struct arphdr) && 435111888Sjlemon ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) { 436111888Sjlemon log(LOG_ERR, "arp: runt packet -- m_pullup failed\n"); 437111888Sjlemon return; 438111888Sjlemon } 439111888Sjlemon ar = mtod(m, struct arphdr *); 4401541Srgrimes 441111888Sjlemon if (ntohs(ar->ar_hrd) != ARPHRD_ETHER && 442111888Sjlemon ntohs(ar->ar_hrd) != ARPHRD_IEEE802 && 443130407Sdfr ntohs(ar->ar_hrd) != ARPHRD_ARCNET && 444130407Sdfr ntohs(ar->ar_hrd) != ARPHRD_IEEE1394) { 445111888Sjlemon log(LOG_ERR, "arp: unknown hardware address format (0x%2D)\n", 446111888Sjlemon (unsigned char *)&ar->ar_hrd, ""); 447111888Sjlemon m_freem(m); 448111888Sjlemon return; 449111888Sjlemon } 4501541Srgrimes 451123768Sru if (m->m_len < arphdr_len(ar)) { 452123765Sru if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { 453123765Sru log(LOG_ERR, "arp: runt packet\n"); 454123765Sru m_freem(m); 455123765Sru return; 456123765Sru } 457123765Sru ar = mtod(m, struct arphdr *); 458111888Sjlemon } 45957900Srwatson 460196797Sgnn ARPSTAT_INC(received); 461111888Sjlemon switch (ntohs(ar->ar_pro)) { 46232350Seivind#ifdef INET 463111888Sjlemon case ETHERTYPE_IP: 464111888Sjlemon in_arpinput(m); 465111888Sjlemon return; 46632350Seivind#endif 4671541Srgrimes } 468111888Sjlemon m_freem(m); 4691541Srgrimes} 4701541Srgrimes 47132350Seivind#ifdef INET 4721541Srgrimes/* 4731541Srgrimes * ARP for Internet protocols on 10 Mb/s Ethernet. 4741541Srgrimes * Algorithm is that given in RFC 826. 4751541Srgrimes * In addition, a sanity check is performed on the sender 4761541Srgrimes * protocol address, to catch impersonators. 4771541Srgrimes * We no longer handle negotiations for use of trailer protocol: 4781541Srgrimes * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent 4791541Srgrimes * along with IP replies if we wanted trailers sent to us, 4801541Srgrimes * and also sent them in response to IP replies. 4811541Srgrimes * This allowed either end to announce the desire to receive 4821541Srgrimes * trailer packets. 4831541Srgrimes * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, 4841541Srgrimes * but formerly didn't normally send requests. 4851541Srgrimes */ 48670699Salfredstatic int log_arp_wrong_iface = 1; 48782893Salfredstatic int log_arp_movements = 1; 488153513Sglebiusstatic int log_arp_permanent_modify = 1; 48970699Salfred 49070699SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW, 49170699Salfred &log_arp_wrong_iface, 0, 49270699Salfred "log arp packets arriving on the wrong interface"); 49382893SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_movements, CTLFLAG_RW, 49482893Salfred &log_arp_movements, 0, 49582966Salfred "log arp replies from MACs different than the one in the cache"); 496153513SglebiusSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_permanent_modify, CTLFLAG_RW, 497153513Sglebius &log_arp_permanent_modify, 0, 498153513Sglebius "log arp replies from MACs different than the one in the permanent arp entry"); 49970699Salfred 50082893Salfred 5011541Srgrimesstatic void 502169454Srwatsonin_arpinput(struct mbuf *m) 5031541Srgrimes{ 504126936Smdodd struct arphdr *ah; 505126936Smdodd struct ifnet *ifp = m->m_pkthdr.rcvif; 506186119Sqingli struct llentry *la = NULL; 507126936Smdodd struct rtentry *rt; 50884102Sjlemon struct ifaddr *ifa; 50984102Sjlemon struct in_ifaddr *ia; 5101541Srgrimes struct sockaddr sa; 5111541Srgrimes struct in_addr isaddr, itaddr, myaddr; 512142215Sglebius u_int8_t *enaddr = NULL; 513186119Sqingli int op, flags; 51484931Sfjoe int req_len; 515181824Sphilip int bridged = 0, is_bridge = 0; 516143314Sglebius int carp_match = 0; 517174559Skmacy struct sockaddr_in sin; 518174559Skmacy sin.sin_len = sizeof(struct sockaddr_in); 519174559Skmacy sin.sin_family = AF_INET; 520174703Skmacy sin.sin_addr.s_addr = 0; 521183550Szec 522155018Sthompsa if (ifp->if_bridge) 523146986Sthompsa bridged = 1; 524181824Sphilip if (ifp->if_type == IFT_BRIDGE) 525181824Sphilip is_bridge = 1; 526146986Sthompsa 52784931Sfjoe req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); 52884931Sfjoe if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) { 52974851Syar log(LOG_ERR, "in_arp: runt packet -- m_pullup failed\n"); 53074851Syar return; 53174851Syar } 53274851Syar 53384931Sfjoe ah = mtod(m, struct arphdr *); 53484931Sfjoe op = ntohs(ah->ar_op); 53584931Sfjoe (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 53684931Sfjoe (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 537134991Sglebius 538196797Sgnn if (op == ARPOP_REPLY) 539196797Sgnn ARPSTAT_INC(rxreplies); 540196797Sgnn 54184102Sjlemon /* 54284102Sjlemon * For a bridge, we want to check the address irrespective 54384102Sjlemon * of the receive interface. (This will change slightly 54484102Sjlemon * when we have clusters of interfaces). 545142215Sglebius * If the interface does not match, but the recieving interface 546142215Sglebius * is part of carp, we call carp_iamatch to see if this is a 547142215Sglebius * request for the virtual host ip. 548142215Sglebius * XXX: This is really ugly! 54984102Sjlemon */ 550194951Srwatson IN_IFADDR_RLOCK(); 551143314Sglebius LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 552156409Sthompsa if (((bridged && ia->ia_ifp->if_bridge != NULL) || 553186119Sqingli ia->ia_ifp == ifp) && 554194820Srwatson itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 555194820Srwatson ifa_ref(&ia->ia_ifa); 556194951Srwatson IN_IFADDR_RUNLOCK(); 557143314Sglebius goto match; 558194820Srwatson } 559143314Sglebius if (ifp->if_carp != NULL && 560211157Swill (*carp_iamatch_p)(ifp, ia, &isaddr, &enaddr) && 561143314Sglebius itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 562143314Sglebius carp_match = 1; 563194820Srwatson ifa_ref(&ia->ia_ifa); 564194951Srwatson IN_IFADDR_RUNLOCK(); 565143314Sglebius goto match; 566143314Sglebius } 567143314Sglebius } 56884102Sjlemon LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) 569156409Sthompsa if (((bridged && ia->ia_ifp->if_bridge != NULL) || 570186119Sqingli ia->ia_ifp == ifp) && 571194820Srwatson isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 572194820Srwatson ifa_ref(&ia->ia_ifa); 573194951Srwatson IN_IFADDR_RUNLOCK(); 57484102Sjlemon goto match; 575194820Srwatson } 576181824Sphilip 577181824Sphilip#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ 578181824Sphilip (ia->ia_ifp->if_bridge == ifp->if_softc && \ 579181824Sphilip !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ 580181824Sphilip addr == ia->ia_addr.sin_addr.s_addr) 58184102Sjlemon /* 582181824Sphilip * Check the case when bridge shares its MAC address with 583181824Sphilip * some of its children, so packets are claimed by bridge 584181824Sphilip * itself (bridge_input() does it first), but they are really 585181824Sphilip * meant to be destined to the bridge member. 586181824Sphilip */ 587181824Sphilip if (is_bridge) { 588181824Sphilip LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 589181824Sphilip if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { 590194820Srwatson ifa_ref(&ia->ia_ifa); 591181824Sphilip ifp = ia->ia_ifp; 592194951Srwatson IN_IFADDR_RUNLOCK(); 593181824Sphilip goto match; 594181824Sphilip } 595181824Sphilip } 596181824Sphilip } 597181824Sphilip#undef BDG_MEMBER_MATCHES_ARP 598194951Srwatson IN_IFADDR_RUNLOCK(); 599181824Sphilip 600181824Sphilip /* 60185223Sjlemon * No match, use the first inet address on the receive interface 60284102Sjlemon * as a dummy address for the rest of the function. 60384102Sjlemon */ 604194820Srwatson IF_ADDR_LOCK(ifp); 60585223Sjlemon TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 606160038Syar if (ifa->ifa_addr->sa_family == AF_INET) { 60785466Sjlemon ia = ifatoia(ifa); 608194820Srwatson ifa_ref(ifa); 609194837Srwatson IF_ADDR_UNLOCK(ifp); 61085466Sjlemon goto match; 61185466Sjlemon } 612194820Srwatson IF_ADDR_UNLOCK(ifp); 613194820Srwatson 61485466Sjlemon /* 61585466Sjlemon * If bridging, fall back to using any inet address. 61685466Sjlemon */ 617194951Srwatson IN_IFADDR_RLOCK(); 618194951Srwatson if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) { 619194951Srwatson IN_IFADDR_RUNLOCK(); 620128645Sluigi goto drop; 621194951Srwatson } 622194820Srwatson ifa_ref(&ia->ia_ifa); 623194951Srwatson IN_IFADDR_RUNLOCK(); 62484102Sjlemonmatch: 625142215Sglebius if (!enaddr) 626142215Sglebius enaddr = (u_int8_t *)IF_LLADDR(ifp); 62784102Sjlemon myaddr = ia->ia_addr.sin_addr; 628194820Srwatson ifa_free(&ia->ia_ifa); 629142215Sglebius if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) 630128645Sluigi goto drop; /* it's from me, ignore it. */ 63184931Sfjoe if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { 6321541Srgrimes log(LOG_ERR, 63384931Sfjoe "arp: link address is broadcast for IP address %s!\n", 6347088Swollman inet_ntoa(isaddr)); 635128645Sluigi goto drop; 6361541Srgrimes } 637136441Srwatson /* 638136441Srwatson * Warn if another host is using the same IP address, but only if the 639136441Srwatson * IP address isn't 0.0.0.0, which is used for DHCP only, in which 640136441Srwatson * case we suppress the warning to avoid false positive complaints of 641136441Srwatson * potential misconfiguration. 642136441Srwatson */ 643150942Sthompsa if (!bridged && isaddr.s_addr == myaddr.s_addr && myaddr.s_addr != 0) { 6441541Srgrimes log(LOG_ERR, 645174256Syar "arp: %*D is using my IP address %s on %s!\n", 64684931Sfjoe ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 647174256Syar inet_ntoa(isaddr), ifp->if_xname); 6481541Srgrimes itaddr = myaddr; 649196797Sgnn ARPSTAT_INC(dupips); 6501541Srgrimes goto reply; 6511541Srgrimes } 652120626Sru if (ifp->if_flags & IFF_STATICARP) 653120626Sru goto reply; 654148955Sglebius 655186119Sqingli bzero(&sin, sizeof(sin)); 656186119Sqingli sin.sin_len = sizeof(struct sockaddr_in); 657186119Sqingli sin.sin_family = AF_INET; 658186119Sqingli sin.sin_addr = isaddr; 659186119Sqingli flags = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0; 660186119Sqingli flags |= LLE_EXCLUSIVE; 661186119Sqingli IF_AFDATA_LOCK(ifp); 662186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin); 663186119Sqingli IF_AFDATA_UNLOCK(ifp); 664186119Sqingli if (la != NULL) { 665186119Sqingli /* the following is not an error when doing bridging */ 666211157Swill if (!bridged && la->lle_tbl->llt_ifp != ifp && !carp_match) { 667186119Sqingli if (log_arp_wrong_iface) 668186119Sqingli log(LOG_ERR, "arp: %s is on %s " 669186119Sqingli "but got reply from %*D on %s\n", 670186119Sqingli inet_ntoa(isaddr), 671186119Sqingli la->lle_tbl->llt_ifp->if_xname, 672186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 673186119Sqingli ifp->if_xname); 674196738Sbz LLE_WUNLOCK(la); 675186119Sqingli goto reply; 676186119Sqingli } 677186119Sqingli if ((la->la_flags & LLE_VALID) && 678186119Sqingli bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { 679186119Sqingli if (la->la_flags & LLE_STATIC) { 680196738Sbz LLE_WUNLOCK(la); 681186119Sqingli log(LOG_ERR, 682186119Sqingli "arp: %*D attempts to modify permanent " 683186119Sqingli "entry for %s on %s\n", 684186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 685186119Sqingli inet_ntoa(isaddr), ifp->if_xname); 686186119Sqingli goto reply; 687178888Sjulian } 688186119Sqingli if (log_arp_movements) { 689186119Sqingli log(LOG_INFO, "arp: %s moved from %*D " 690186119Sqingli "to %*D on %s\n", 691186119Sqingli inet_ntoa(isaddr), 692186119Sqingli ifp->if_addrlen, 693186119Sqingli (u_char *)&la->ll_addr, ":", 694186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 695186119Sqingli ifp->if_xname); 696178888Sjulian } 697178888Sjulian } 698186119Sqingli 699186119Sqingli if (ifp->if_addrlen != ah->ar_hln) { 700196738Sbz LLE_WUNLOCK(la); 701186119Sqingli log(LOG_WARNING, 702186119Sqingli "arp from %*D: addr len: new %d, i/f %d (ignored)", 703186119Sqingli ifp->if_addrlen, (u_char *) ar_sha(ah), ":", 704186119Sqingli ah->ar_hln, ifp->if_addrlen); 705186119Sqingli goto reply; 706178888Sjulian } 707186119Sqingli (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); 708186119Sqingli la->la_flags |= LLE_VALID; 709178888Sjulian 710196995Snp EVENTHANDLER_INVOKE(arp_update_event, la); 711196995Snp 712186119Sqingli if (!(la->la_flags & LLE_STATIC)) { 713206481Sbz int canceled; 714206481Sbz 715206481Sbz LLE_ADDREF(la); 716216075Sglebius la->la_expire = time_uptime + V_arpt_keep; 717206481Sbz canceled = callout_reset(&la->la_timer, 718206481Sbz hz * V_arpt_keep, arptimer, la); 719206481Sbz if (canceled) 720206481Sbz LLE_REMREF(la); 72139389Sfenner } 722178888Sjulian la->la_asked = 0; 723181803Sbz la->la_preempt = V_arp_maxtries; 724215207Sgnn /* 725215207Sgnn * The packets are all freed within the call to the output 726215207Sgnn * routine. 727215207Sgnn * 728215207Sgnn * NB: The lock MUST be released before the call to the 729215207Sgnn * output routine. 730215207Sgnn */ 731215207Sgnn if (la->la_hold != NULL) { 732215207Sgnn struct mbuf *m_hold, *m_hold_next; 733215207Sgnn 734217113Sgnn m_hold = la->la_hold; 735217113Sgnn la->la_hold = NULL; 736217113Sgnn la->la_numheld = 0; 737186119Sqingli memcpy(&sa, L3_ADDR(la), sizeof(sa)); 738215207Sgnn LLE_WUNLOCK(la); 739215207Sgnn for (m_hold = la->la_hold, la->la_hold = NULL; 740215207Sgnn m_hold != NULL; m_hold = m_hold_next) { 741215207Sgnn m_hold_next = m_hold->m_nextpkt; 742215207Sgnn m_hold->m_nextpkt = NULL; 743215207Sgnn (*ifp->if_output)(ifp, m_hold, &sa, NULL); 744215207Sgnn } 745215207Sgnn } else 746215207Sgnn LLE_WUNLOCK(la); 747215207Sgnn } /* end of FIB loop */ 748178888Sjulianreply: 749128645Sluigi if (op != ARPOP_REQUEST) 750128645Sluigi goto drop; 751196797Sgnn ARPSTAT_INC(rxrequests); 752186119Sqingli 7531541Srgrimes if (itaddr.s_addr == myaddr.s_addr) { 754178888Sjulian /* Shortcut.. the receiving interface is the target. */ 75584931Sfjoe (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 756142215Sglebius (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 7571541Srgrimes } else { 758186317Sqingli struct llentry *lle = NULL; 7593282Swollman 760186317Sqingli sin.sin_addr = itaddr; 761197225Sqingli IF_AFDATA_LOCK(ifp); 762197225Sqingli lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin); 763197225Sqingli IF_AFDATA_UNLOCK(ifp); 764186317Sqingli 765197225Sqingli if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { 766186317Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 767186317Sqingli (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); 768186317Sqingli LLE_RUNLOCK(lle); 769197225Sqingli } else { 77063080Sdwmalone 771197225Sqingli if (lle != NULL) 772197225Sqingli LLE_RUNLOCK(lle); 773186317Sqingli 774197225Sqingli if (!V_arp_proxyall) 775197225Sqingli goto drop; 776197225Sqingli 777197225Sqingli sin.sin_addr = itaddr; 778197225Sqingli /* XXX MRT use table 0 for arp reply */ 779197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 780197225Sqingli if (!rt) 781197225Sqingli goto drop; 782197225Sqingli 783197225Sqingli /* 784197225Sqingli * Don't send proxies for nodes on the same interface 785197225Sqingli * as this one came out of, or we'll get into a fight 786197225Sqingli * over who claims what Ether address. 787197225Sqingli */ 788197225Sqingli if (!rt->rt_ifp || rt->rt_ifp == ifp) { 789197225Sqingli RTFREE_LOCKED(rt); 790197225Sqingli goto drop; 791197225Sqingli } 792185713Scsjp RTFREE_LOCKED(rt); 79363080Sdwmalone 794197225Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 795197225Sqingli (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 796197225Sqingli 797197225Sqingli /* 798197225Sqingli * Also check that the node which sent the ARP packet 799197225Sqingli * is on the the interface we expect it to be on. This 800197225Sqingli * avoids ARP chaos if an interface is connected to the 801197225Sqingli * wrong network. 802197225Sqingli */ 803197225Sqingli sin.sin_addr = isaddr; 804197225Sqingli 805197225Sqingli /* XXX MRT use table 0 for arp checks */ 806197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 807197225Sqingli if (!rt) 808197225Sqingli goto drop; 809197225Sqingli if (rt->rt_ifp != ifp) { 810197225Sqingli log(LOG_INFO, "arp_proxy: ignoring request" 811197225Sqingli " from %s via %s, expecting %s\n", 812197225Sqingli inet_ntoa(isaddr), ifp->if_xname, 813197225Sqingli rt->rt_ifp->if_xname); 814197225Sqingli RTFREE_LOCKED(rt); 815197225Sqingli goto drop; 816197225Sqingli } 817197225Sqingli RTFREE_LOCKED(rt); 818197225Sqingli 8194069Swollman#ifdef DEBUG_PROXY 820197225Sqingli printf("arp: proxying for %s\n", 821197225Sqingli inet_ntoa(itaddr)); 8224069Swollman#endif 823197225Sqingli } 8241541Srgrimes } 8251541Srgrimes 826166436Sbms if (itaddr.s_addr == myaddr.s_addr && 827166436Sbms IN_LINKLOCAL(ntohl(itaddr.s_addr))) { 828166436Sbms /* RFC 3927 link-local IPv4; always reply by broadcast. */ 829166436Sbms#ifdef DEBUG_LINKLOCAL 830166436Sbms printf("arp: sending reply for link-local addr %s\n", 831166436Sbms inet_ntoa(itaddr)); 832166436Sbms#endif 833166436Sbms m->m_flags |= M_BCAST; 834166436Sbms m->m_flags &= ~M_MCAST; 835166436Sbms } else { 836166436Sbms /* default behaviour; never reply by broadcast. */ 837166436Sbms m->m_flags &= ~(M_BCAST|M_MCAST); 838166436Sbms } 83984931Sfjoe (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); 84084931Sfjoe (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 84184931Sfjoe ah->ar_op = htons(ARPOP_REPLY); 84284931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 843127261Smdodd m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 844127261Smdodd m->m_pkthdr.len = m->m_len; 845127261Smdodd sa.sa_family = AF_ARP; 846127261Smdodd sa.sa_len = 2; 847191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 848196797Sgnn ARPSTAT_INC(txreplies); 8491541Srgrimes return; 850128645Sluigi 851128645Sluigidrop: 852128645Sluigi m_freem(m); 8531541Srgrimes} 85432350Seivind#endif 8551541Srgrimes 8565195Swollmanvoid 857169454Srwatsonarp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) 8585195Swollman{ 859186119Sqingli struct llentry *lle; 860186119Sqingli 861186411Sqingli if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) { 86284931Sfjoe arprequest(ifp, &IA_SIN(ifa)->sin_addr, 86384931Sfjoe &IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp)); 864186411Sqingli /* 865186411Sqingli * interface address is considered static entry 866186411Sqingli * because the output of the arp utility shows 867186411Sqingli * that L2 entry as permanent 868186411Sqingli */ 869186411Sqingli IF_AFDATA_LOCK(ifp); 870186411Sqingli lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC), 871186411Sqingli (struct sockaddr *)IA_SIN(ifa)); 872186411Sqingli IF_AFDATA_UNLOCK(ifp); 873186411Sqingli if (lle == NULL) 874186411Sqingli log(LOG_INFO, "arp_ifinit: cannot create arp " 875186411Sqingli "entry for interface address\n"); 876186411Sqingli else 877186411Sqingli LLE_RUNLOCK(lle); 878186411Sqingli } 879186119Sqingli ifa->ifa_rtrequest = NULL; 8805195Swollman} 88169152Sjlemon 882142215Sglebiusvoid 883169454Srwatsonarp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr) 884142215Sglebius{ 885142215Sglebius if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) 886142215Sglebius arprequest(ifp, &IA_SIN(ifa)->sin_addr, 887142215Sglebius &IA_SIN(ifa)->sin_addr, enaddr); 888186119Sqingli ifa->ifa_rtrequest = NULL; 889142215Sglebius} 890142215Sglebius 891190787Szecstatic void 892190787Szecarp_init(void) 893190787Szec{ 894190787Szec 895193219Srwatson netisr_register(&arp_nh); 89669152Sjlemon} 89769152SjlemonSYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); 898