if_ether.c revision 223840
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 223840 2011-07-07 11:59:51Z ae $"); 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 && 444219819Sjeff ntohs(ar->ar_hrd) != ARPHRD_IEEE1394 && 445219819Sjeff ntohs(ar->ar_hrd) != ARPHRD_INFINIBAND) { 446111888Sjlemon log(LOG_ERR, "arp: unknown hardware address format (0x%2D)\n", 447111888Sjlemon (unsigned char *)&ar->ar_hrd, ""); 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) { 454123765Sru log(LOG_ERR, "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; 517143314Sglebius int carp_match = 0; 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) { 53074851Syar log(LOG_ERR, "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)) { 540217333Scsjp log(LOG_ERR, "in_arp: requested protocol length != %zu\n", 541217315Sgnn sizeof(struct in_addr)); 542217315Sgnn return; 543217315Sgnn } 544217315Sgnn 545217315Sgnn if (ETHER_IS_MULTICAST(ar_sha(ah))) { 546217315Sgnn log(LOG_ERR, "in_arp: source hardware address is multicast."); 547217315Sgnn return; 548217315Sgnn } 549217315Sgnn 55084931Sfjoe op = ntohs(ah->ar_op); 55184931Sfjoe (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 55284931Sfjoe (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 553134991Sglebius 554196797Sgnn if (op == ARPOP_REPLY) 555196797Sgnn ARPSTAT_INC(rxreplies); 556196797Sgnn 55784102Sjlemon /* 55884102Sjlemon * For a bridge, we want to check the address irrespective 55984102Sjlemon * of the receive interface. (This will change slightly 56084102Sjlemon * when we have clusters of interfaces). 561142215Sglebius * If the interface does not match, but the recieving interface 562142215Sglebius * is part of carp, we call carp_iamatch to see if this is a 563142215Sglebius * request for the virtual host ip. 564142215Sglebius * XXX: This is really ugly! 56584102Sjlemon */ 566194951Srwatson IN_IFADDR_RLOCK(); 567143314Sglebius LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 568217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 569186119Sqingli ia->ia_ifp == ifp) && 570194820Srwatson itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 571194820Srwatson ifa_ref(&ia->ia_ifa); 572194951Srwatson IN_IFADDR_RUNLOCK(); 573143314Sglebius goto match; 574194820Srwatson } 575143314Sglebius if (ifp->if_carp != NULL && 576211157Swill (*carp_iamatch_p)(ifp, ia, &isaddr, &enaddr) && 577143314Sglebius itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 578143314Sglebius carp_match = 1; 579194820Srwatson ifa_ref(&ia->ia_ifa); 580194951Srwatson IN_IFADDR_RUNLOCK(); 581143314Sglebius goto match; 582143314Sglebius } 583143314Sglebius } 58484102Sjlemon LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) 585217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 586186119Sqingli ia->ia_ifp == ifp) && 587194820Srwatson isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 588194820Srwatson ifa_ref(&ia->ia_ifa); 589194951Srwatson IN_IFADDR_RUNLOCK(); 59084102Sjlemon goto match; 591194820Srwatson } 592181824Sphilip 593181824Sphilip#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ 594181824Sphilip (ia->ia_ifp->if_bridge == ifp->if_softc && \ 595181824Sphilip !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ 596181824Sphilip addr == ia->ia_addr.sin_addr.s_addr) 59784102Sjlemon /* 598181824Sphilip * Check the case when bridge shares its MAC address with 599181824Sphilip * some of its children, so packets are claimed by bridge 600181824Sphilip * itself (bridge_input() does it first), but they are really 601181824Sphilip * meant to be destined to the bridge member. 602181824Sphilip */ 603181824Sphilip if (is_bridge) { 604181824Sphilip LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 605181824Sphilip if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { 606194820Srwatson ifa_ref(&ia->ia_ifa); 607181824Sphilip ifp = ia->ia_ifp; 608194951Srwatson IN_IFADDR_RUNLOCK(); 609181824Sphilip goto match; 610181824Sphilip } 611181824Sphilip } 612181824Sphilip } 613181824Sphilip#undef BDG_MEMBER_MATCHES_ARP 614194951Srwatson IN_IFADDR_RUNLOCK(); 615181824Sphilip 616181824Sphilip /* 61785223Sjlemon * No match, use the first inet address on the receive interface 61884102Sjlemon * as a dummy address for the rest of the function. 61984102Sjlemon */ 620194820Srwatson IF_ADDR_LOCK(ifp); 62185223Sjlemon TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 622160038Syar if (ifa->ifa_addr->sa_family == AF_INET) { 62385466Sjlemon ia = ifatoia(ifa); 624194820Srwatson ifa_ref(ifa); 625194837Srwatson IF_ADDR_UNLOCK(ifp); 62685466Sjlemon goto match; 62785466Sjlemon } 628194820Srwatson IF_ADDR_UNLOCK(ifp); 629194820Srwatson 63085466Sjlemon /* 63185466Sjlemon * If bridging, fall back to using any inet address. 63285466Sjlemon */ 633194951Srwatson IN_IFADDR_RLOCK(); 634194951Srwatson if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) { 635194951Srwatson IN_IFADDR_RUNLOCK(); 636128645Sluigi goto drop; 637194951Srwatson } 638194820Srwatson ifa_ref(&ia->ia_ifa); 639194951Srwatson IN_IFADDR_RUNLOCK(); 64084102Sjlemonmatch: 641142215Sglebius if (!enaddr) 642142215Sglebius enaddr = (u_int8_t *)IF_LLADDR(ifp); 64384102Sjlemon myaddr = ia->ia_addr.sin_addr; 644194820Srwatson ifa_free(&ia->ia_ifa); 645142215Sglebius if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) 646128645Sluigi goto drop; /* it's from me, ignore it. */ 64784931Sfjoe if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { 6481541Srgrimes log(LOG_ERR, 64984931Sfjoe "arp: link address is broadcast for IP address %s!\n", 6507088Swollman inet_ntoa(isaddr)); 651128645Sluigi goto drop; 6521541Srgrimes } 653136441Srwatson /* 654136441Srwatson * Warn if another host is using the same IP address, but only if the 655136441Srwatson * IP address isn't 0.0.0.0, which is used for DHCP only, in which 656136441Srwatson * case we suppress the warning to avoid false positive complaints of 657136441Srwatson * potential misconfiguration. 658136441Srwatson */ 659150942Sthompsa if (!bridged && isaddr.s_addr == myaddr.s_addr && myaddr.s_addr != 0) { 6601541Srgrimes log(LOG_ERR, 661174256Syar "arp: %*D is using my IP address %s on %s!\n", 66284931Sfjoe ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 663174256Syar inet_ntoa(isaddr), ifp->if_xname); 6641541Srgrimes itaddr = myaddr; 665196797Sgnn ARPSTAT_INC(dupips); 6661541Srgrimes goto reply; 6671541Srgrimes } 668120626Sru if (ifp->if_flags & IFF_STATICARP) 669120626Sru goto reply; 670148955Sglebius 671186119Sqingli bzero(&sin, sizeof(sin)); 672186119Sqingli sin.sin_len = sizeof(struct sockaddr_in); 673186119Sqingli sin.sin_family = AF_INET; 674186119Sqingli sin.sin_addr = isaddr; 675186119Sqingli flags = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0; 676186119Sqingli flags |= LLE_EXCLUSIVE; 677186119Sqingli IF_AFDATA_LOCK(ifp); 678186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin); 679186119Sqingli IF_AFDATA_UNLOCK(ifp); 680186119Sqingli if (la != NULL) { 681186119Sqingli /* the following is not an error when doing bridging */ 682211157Swill if (!bridged && la->lle_tbl->llt_ifp != ifp && !carp_match) { 683186119Sqingli if (log_arp_wrong_iface) 684186119Sqingli log(LOG_ERR, "arp: %s is on %s " 685186119Sqingli "but got reply from %*D on %s\n", 686186119Sqingli inet_ntoa(isaddr), 687186119Sqingli la->lle_tbl->llt_ifp->if_xname, 688186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 689186119Sqingli ifp->if_xname); 690196738Sbz LLE_WUNLOCK(la); 691186119Sqingli goto reply; 692186119Sqingli } 693186119Sqingli if ((la->la_flags & LLE_VALID) && 694186119Sqingli bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { 695186119Sqingli if (la->la_flags & LLE_STATIC) { 696196738Sbz LLE_WUNLOCK(la); 697223840Sae if (log_arp_permanent_modify) 698223840Sae log(LOG_ERR, 699223840Sae "arp: %*D attempts to modify " 700223840Sae "permanent entry for %s on %s\n", 701223840Sae ifp->if_addrlen, 702223840Sae (u_char *)ar_sha(ah), ":", 703223840Sae inet_ntoa(isaddr), ifp->if_xname); 704186119Sqingli goto reply; 705178888Sjulian } 706186119Sqingli if (log_arp_movements) { 707186119Sqingli log(LOG_INFO, "arp: %s moved from %*D " 708186119Sqingli "to %*D on %s\n", 709186119Sqingli inet_ntoa(isaddr), 710186119Sqingli ifp->if_addrlen, 711186119Sqingli (u_char *)&la->ll_addr, ":", 712186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 713186119Sqingli ifp->if_xname); 714178888Sjulian } 715178888Sjulian } 716186119Sqingli 717186119Sqingli if (ifp->if_addrlen != ah->ar_hln) { 718196738Sbz LLE_WUNLOCK(la); 719186119Sqingli log(LOG_WARNING, 720186119Sqingli "arp from %*D: addr len: new %d, i/f %d (ignored)", 721186119Sqingli ifp->if_addrlen, (u_char *) ar_sha(ah), ":", 722186119Sqingli ah->ar_hln, ifp->if_addrlen); 723217315Sgnn goto drop; 724178888Sjulian } 725186119Sqingli (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); 726186119Sqingli la->la_flags |= LLE_VALID; 727178888Sjulian 728196995Snp EVENTHANDLER_INVOKE(arp_update_event, la); 729196995Snp 730186119Sqingli if (!(la->la_flags & LLE_STATIC)) { 731206481Sbz int canceled; 732206481Sbz 733206481Sbz LLE_ADDREF(la); 734216075Sglebius la->la_expire = time_uptime + V_arpt_keep; 735206481Sbz canceled = callout_reset(&la->la_timer, 736206481Sbz hz * V_arpt_keep, arptimer, la); 737206481Sbz if (canceled) 738206481Sbz LLE_REMREF(la); 73939389Sfenner } 740178888Sjulian la->la_asked = 0; 741181803Sbz la->la_preempt = V_arp_maxtries; 742215207Sgnn /* 743215207Sgnn * The packets are all freed within the call to the output 744215207Sgnn * routine. 745215207Sgnn * 746215207Sgnn * NB: The lock MUST be released before the call to the 747215207Sgnn * output routine. 748215207Sgnn */ 749215207Sgnn if (la->la_hold != NULL) { 750215207Sgnn struct mbuf *m_hold, *m_hold_next; 751215207Sgnn 752217113Sgnn m_hold = la->la_hold; 753217113Sgnn la->la_hold = NULL; 754217113Sgnn la->la_numheld = 0; 755186119Sqingli memcpy(&sa, L3_ADDR(la), sizeof(sa)); 756215207Sgnn LLE_WUNLOCK(la); 757217121Sgnn for (; m_hold != NULL; m_hold = m_hold_next) { 758215207Sgnn m_hold_next = m_hold->m_nextpkt; 759215207Sgnn m_hold->m_nextpkt = NULL; 760215207Sgnn (*ifp->if_output)(ifp, m_hold, &sa, NULL); 761215207Sgnn } 762215207Sgnn } else 763215207Sgnn LLE_WUNLOCK(la); 764223261Sbz } 765178888Sjulianreply: 766128645Sluigi if (op != ARPOP_REQUEST) 767128645Sluigi goto drop; 768196797Sgnn ARPSTAT_INC(rxrequests); 769186119Sqingli 7701541Srgrimes if (itaddr.s_addr == myaddr.s_addr) { 771178888Sjulian /* Shortcut.. the receiving interface is the target. */ 77284931Sfjoe (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 773142215Sglebius (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 7741541Srgrimes } else { 775186317Sqingli struct llentry *lle = NULL; 7763282Swollman 777186317Sqingli sin.sin_addr = itaddr; 778197225Sqingli IF_AFDATA_LOCK(ifp); 779197225Sqingli lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin); 780197225Sqingli IF_AFDATA_UNLOCK(ifp); 781186317Sqingli 782197225Sqingli if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { 783186317Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 784186317Sqingli (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); 785186317Sqingli LLE_RUNLOCK(lle); 786197225Sqingli } else { 78763080Sdwmalone 788197225Sqingli if (lle != NULL) 789197225Sqingli LLE_RUNLOCK(lle); 790186317Sqingli 791197225Sqingli if (!V_arp_proxyall) 792197225Sqingli goto drop; 793197225Sqingli 794197225Sqingli sin.sin_addr = itaddr; 795197225Sqingli /* XXX MRT use table 0 for arp reply */ 796197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 797197225Sqingli if (!rt) 798197225Sqingli goto drop; 799197225Sqingli 800197225Sqingli /* 801197225Sqingli * Don't send proxies for nodes on the same interface 802197225Sqingli * as this one came out of, or we'll get into a fight 803197225Sqingli * over who claims what Ether address. 804197225Sqingli */ 805197225Sqingli if (!rt->rt_ifp || rt->rt_ifp == ifp) { 806197225Sqingli RTFREE_LOCKED(rt); 807197225Sqingli goto drop; 808197225Sqingli } 809185713Scsjp RTFREE_LOCKED(rt); 81063080Sdwmalone 811197225Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 812197225Sqingli (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 813197225Sqingli 814197225Sqingli /* 815197225Sqingli * Also check that the node which sent the ARP packet 816218909Sbrucec * is on the interface we expect it to be on. This 817197225Sqingli * avoids ARP chaos if an interface is connected to the 818197225Sqingli * wrong network. 819197225Sqingli */ 820197225Sqingli sin.sin_addr = isaddr; 821197225Sqingli 822197225Sqingli /* XXX MRT use table 0 for arp checks */ 823197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 824197225Sqingli if (!rt) 825197225Sqingli goto drop; 826197225Sqingli if (rt->rt_ifp != ifp) { 827197225Sqingli log(LOG_INFO, "arp_proxy: ignoring request" 828197225Sqingli " from %s via %s, expecting %s\n", 829197225Sqingli inet_ntoa(isaddr), ifp->if_xname, 830197225Sqingli rt->rt_ifp->if_xname); 831197225Sqingli RTFREE_LOCKED(rt); 832197225Sqingli goto drop; 833197225Sqingli } 834197225Sqingli RTFREE_LOCKED(rt); 835197225Sqingli 8364069Swollman#ifdef DEBUG_PROXY 837197225Sqingli printf("arp: proxying for %s\n", 838197225Sqingli inet_ntoa(itaddr)); 8394069Swollman#endif 840197225Sqingli } 8411541Srgrimes } 8421541Srgrimes 843166436Sbms if (itaddr.s_addr == myaddr.s_addr && 844166436Sbms IN_LINKLOCAL(ntohl(itaddr.s_addr))) { 845166436Sbms /* RFC 3927 link-local IPv4; always reply by broadcast. */ 846166436Sbms#ifdef DEBUG_LINKLOCAL 847166436Sbms printf("arp: sending reply for link-local addr %s\n", 848166436Sbms inet_ntoa(itaddr)); 849166436Sbms#endif 850166436Sbms m->m_flags |= M_BCAST; 851166436Sbms m->m_flags &= ~M_MCAST; 852166436Sbms } else { 853166436Sbms /* default behaviour; never reply by broadcast. */ 854166436Sbms m->m_flags &= ~(M_BCAST|M_MCAST); 855166436Sbms } 85684931Sfjoe (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); 85784931Sfjoe (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 85884931Sfjoe ah->ar_op = htons(ARPOP_REPLY); 85984931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 860127261Smdodd m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 861127261Smdodd m->m_pkthdr.len = m->m_len; 862223753Sae m->m_pkthdr.rcvif = NULL; 863127261Smdodd sa.sa_family = AF_ARP; 864127261Smdodd sa.sa_len = 2; 865191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 866196797Sgnn ARPSTAT_INC(txreplies); 8671541Srgrimes return; 868128645Sluigi 869128645Sluigidrop: 870128645Sluigi m_freem(m); 8711541Srgrimes} 87232350Seivind#endif 8731541Srgrimes 8745195Swollmanvoid 875169454Srwatsonarp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) 8765195Swollman{ 877186119Sqingli struct llentry *lle; 878186119Sqingli 879186411Sqingli if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) { 88084931Sfjoe arprequest(ifp, &IA_SIN(ifa)->sin_addr, 88184931Sfjoe &IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp)); 882186411Sqingli /* 883186411Sqingli * interface address is considered static entry 884186411Sqingli * because the output of the arp utility shows 885186411Sqingli * that L2 entry as permanent 886186411Sqingli */ 887186411Sqingli IF_AFDATA_LOCK(ifp); 888186411Sqingli lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC), 889186411Sqingli (struct sockaddr *)IA_SIN(ifa)); 890186411Sqingli IF_AFDATA_UNLOCK(ifp); 891186411Sqingli if (lle == NULL) 892186411Sqingli log(LOG_INFO, "arp_ifinit: cannot create arp " 893186411Sqingli "entry for interface address\n"); 894186411Sqingli else 895186411Sqingli LLE_RUNLOCK(lle); 896186411Sqingli } 897186119Sqingli ifa->ifa_rtrequest = NULL; 8985195Swollman} 89969152Sjlemon 900142215Sglebiusvoid 901169454Srwatsonarp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr) 902142215Sglebius{ 903142215Sglebius if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) 904142215Sglebius arprequest(ifp, &IA_SIN(ifa)->sin_addr, 905142215Sglebius &IA_SIN(ifa)->sin_addr, enaddr); 906186119Sqingli ifa->ifa_rtrequest = NULL; 907142215Sglebius} 908142215Sglebius 909190787Szecstatic void 910190787Szecarp_init(void) 911190787Szec{ 912190787Szec 913193219Srwatson netisr_register(&arp_nh); 91469152Sjlemon} 91569152SjlemonSYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); 916