if_ether.c revision 227790
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 227790 2011-11-21 13:40:35Z 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 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)) { 436227785Sglebius log(LOG_NOTICE, "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) { 446227790Sglebius log(LOG_NOTICE, "arp: unknown hardware address format (0x%2D)" 447227790Sglebius " (from %*D to %*D)\n", (unsigned char *)&ar->ar_hrd, "", 448227790Sglebius ETHER_ADDR_LEN, (u_char *)ar_sha(ar), ":", 449227790Sglebius ETHER_ADDR_LEN, (u_char *)ar_tha(ar), ":"); 450111888Sjlemon m_freem(m); 451111888Sjlemon return; 452111888Sjlemon } 4531541Srgrimes 454123768Sru if (m->m_len < arphdr_len(ar)) { 455123765Sru if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { 456227785Sglebius log(LOG_NOTICE, "arp: runt packet\n"); 457123765Sru m_freem(m); 458123765Sru return; 459123765Sru } 460123765Sru ar = mtod(m, struct arphdr *); 461111888Sjlemon } 46257900Srwatson 463196797Sgnn ARPSTAT_INC(received); 464111888Sjlemon switch (ntohs(ar->ar_pro)) { 46532350Seivind#ifdef INET 466111888Sjlemon case ETHERTYPE_IP: 467111888Sjlemon in_arpinput(m); 468111888Sjlemon return; 46932350Seivind#endif 4701541Srgrimes } 471111888Sjlemon m_freem(m); 4721541Srgrimes} 4731541Srgrimes 47432350Seivind#ifdef INET 4751541Srgrimes/* 4761541Srgrimes * ARP for Internet protocols on 10 Mb/s Ethernet. 4771541Srgrimes * Algorithm is that given in RFC 826. 4781541Srgrimes * In addition, a sanity check is performed on the sender 4791541Srgrimes * protocol address, to catch impersonators. 4801541Srgrimes * We no longer handle negotiations for use of trailer protocol: 4811541Srgrimes * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent 4821541Srgrimes * along with IP replies if we wanted trailers sent to us, 4831541Srgrimes * and also sent them in response to IP replies. 4841541Srgrimes * This allowed either end to announce the desire to receive 4851541Srgrimes * trailer packets. 4861541Srgrimes * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, 4871541Srgrimes * but formerly didn't normally send requests. 4881541Srgrimes */ 48970699Salfredstatic int log_arp_wrong_iface = 1; 49082893Salfredstatic int log_arp_movements = 1; 491153513Sglebiusstatic int log_arp_permanent_modify = 1; 49270699Salfred 49370699SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW, 49470699Salfred &log_arp_wrong_iface, 0, 49570699Salfred "log arp packets arriving on the wrong interface"); 49682893SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_movements, CTLFLAG_RW, 49782893Salfred &log_arp_movements, 0, 49882966Salfred "log arp replies from MACs different than the one in the cache"); 499153513SglebiusSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_permanent_modify, CTLFLAG_RW, 500153513Sglebius &log_arp_permanent_modify, 0, 501153513Sglebius "log arp replies from MACs different than the one in the permanent arp entry"); 50270699Salfred 50382893Salfred 5041541Srgrimesstatic void 505169454Srwatsonin_arpinput(struct mbuf *m) 5061541Srgrimes{ 507126936Smdodd struct arphdr *ah; 508126936Smdodd struct ifnet *ifp = m->m_pkthdr.rcvif; 509186119Sqingli struct llentry *la = NULL; 510126936Smdodd struct rtentry *rt; 51184102Sjlemon struct ifaddr *ifa; 51284102Sjlemon struct in_ifaddr *ia; 5131541Srgrimes struct sockaddr sa; 5141541Srgrimes struct in_addr isaddr, itaddr, myaddr; 515142215Sglebius u_int8_t *enaddr = NULL; 516186119Sqingli int op, flags; 51784931Sfjoe int req_len; 518181824Sphilip int bridged = 0, is_bridge = 0; 519143314Sglebius int carp_match = 0; 520174559Skmacy struct sockaddr_in sin; 521174559Skmacy sin.sin_len = sizeof(struct sockaddr_in); 522174559Skmacy sin.sin_family = AF_INET; 523174703Skmacy sin.sin_addr.s_addr = 0; 524183550Szec 525155018Sthompsa if (ifp->if_bridge) 526146986Sthompsa bridged = 1; 527181824Sphilip if (ifp->if_type == IFT_BRIDGE) 528181824Sphilip is_bridge = 1; 529146986Sthompsa 53084931Sfjoe req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); 53184931Sfjoe if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) { 532227785Sglebius log(LOG_NOTICE, "in_arp: runt packet -- m_pullup failed\n"); 53374851Syar return; 53474851Syar } 53574851Syar 53684931Sfjoe ah = mtod(m, struct arphdr *); 537217315Sgnn /* 538217315Sgnn * ARP is only for IPv4 so we can reject packets with 539217315Sgnn * a protocol length not equal to an IPv4 address. 540217315Sgnn */ 541217315Sgnn if (ah->ar_pln != sizeof(struct in_addr)) { 542227785Sglebius log(LOG_NOTICE, "in_arp: requested protocol length != %zu\n", 543217315Sgnn sizeof(struct in_addr)); 544217315Sgnn return; 545217315Sgnn } 546217315Sgnn 547217315Sgnn if (ETHER_IS_MULTICAST(ar_sha(ah))) { 548227785Sglebius log(LOG_NOTICE, "in_arp: %*D is multicast\n", 549227785Sglebius ifp->if_addrlen, (u_char *)ar_sha(ah), ":"); 550217315Sgnn return; 551217315Sgnn } 552217315Sgnn 55384931Sfjoe op = ntohs(ah->ar_op); 55484931Sfjoe (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 55584931Sfjoe (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 556134991Sglebius 557196797Sgnn if (op == ARPOP_REPLY) 558196797Sgnn ARPSTAT_INC(rxreplies); 559196797Sgnn 56084102Sjlemon /* 56184102Sjlemon * For a bridge, we want to check the address irrespective 56284102Sjlemon * of the receive interface. (This will change slightly 56384102Sjlemon * when we have clusters of interfaces). 564142215Sglebius * If the interface does not match, but the recieving interface 565142215Sglebius * is part of carp, we call carp_iamatch to see if this is a 566142215Sglebius * request for the virtual host ip. 567142215Sglebius * XXX: This is really ugly! 56884102Sjlemon */ 569194951Srwatson IN_IFADDR_RLOCK(); 570143314Sglebius LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 571217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 572186119Sqingli ia->ia_ifp == ifp) && 573194820Srwatson itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 574194820Srwatson ifa_ref(&ia->ia_ifa); 575194951Srwatson IN_IFADDR_RUNLOCK(); 576143314Sglebius goto match; 577194820Srwatson } 578143314Sglebius if (ifp->if_carp != NULL && 579211157Swill (*carp_iamatch_p)(ifp, ia, &isaddr, &enaddr) && 580143314Sglebius itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 581143314Sglebius carp_match = 1; 582194820Srwatson ifa_ref(&ia->ia_ifa); 583194951Srwatson IN_IFADDR_RUNLOCK(); 584143314Sglebius goto match; 585143314Sglebius } 586143314Sglebius } 58784102Sjlemon LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) 588217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 589186119Sqingli ia->ia_ifp == ifp) && 590194820Srwatson isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 591194820Srwatson ifa_ref(&ia->ia_ifa); 592194951Srwatson IN_IFADDR_RUNLOCK(); 59384102Sjlemon goto match; 594194820Srwatson } 595181824Sphilip 596181824Sphilip#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ 597181824Sphilip (ia->ia_ifp->if_bridge == ifp->if_softc && \ 598181824Sphilip !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ 599181824Sphilip addr == ia->ia_addr.sin_addr.s_addr) 60084102Sjlemon /* 601181824Sphilip * Check the case when bridge shares its MAC address with 602181824Sphilip * some of its children, so packets are claimed by bridge 603181824Sphilip * itself (bridge_input() does it first), but they are really 604181824Sphilip * meant to be destined to the bridge member. 605181824Sphilip */ 606181824Sphilip if (is_bridge) { 607181824Sphilip LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 608181824Sphilip if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { 609194820Srwatson ifa_ref(&ia->ia_ifa); 610181824Sphilip ifp = ia->ia_ifp; 611194951Srwatson IN_IFADDR_RUNLOCK(); 612181824Sphilip goto match; 613181824Sphilip } 614181824Sphilip } 615181824Sphilip } 616181824Sphilip#undef BDG_MEMBER_MATCHES_ARP 617194951Srwatson IN_IFADDR_RUNLOCK(); 618181824Sphilip 619181824Sphilip /* 62085223Sjlemon * No match, use the first inet address on the receive interface 62184102Sjlemon * as a dummy address for the rest of the function. 62284102Sjlemon */ 623194820Srwatson IF_ADDR_LOCK(ifp); 62485223Sjlemon TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 625160038Syar if (ifa->ifa_addr->sa_family == AF_INET) { 62685466Sjlemon ia = ifatoia(ifa); 627194820Srwatson ifa_ref(ifa); 628194837Srwatson IF_ADDR_UNLOCK(ifp); 62985466Sjlemon goto match; 63085466Sjlemon } 631194820Srwatson IF_ADDR_UNLOCK(ifp); 632194820Srwatson 63385466Sjlemon /* 63485466Sjlemon * If bridging, fall back to using any inet address. 63585466Sjlemon */ 636194951Srwatson IN_IFADDR_RLOCK(); 637194951Srwatson if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) { 638194951Srwatson IN_IFADDR_RUNLOCK(); 639128645Sluigi goto drop; 640194951Srwatson } 641194820Srwatson ifa_ref(&ia->ia_ifa); 642194951Srwatson IN_IFADDR_RUNLOCK(); 64384102Sjlemonmatch: 644142215Sglebius if (!enaddr) 645142215Sglebius enaddr = (u_int8_t *)IF_LLADDR(ifp); 64684102Sjlemon myaddr = ia->ia_addr.sin_addr; 647194820Srwatson ifa_free(&ia->ia_ifa); 648142215Sglebius if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) 649128645Sluigi goto drop; /* it's from me, ignore it. */ 65084931Sfjoe if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { 651227785Sglebius log(LOG_NOTICE, 65284931Sfjoe "arp: link address is broadcast for IP address %s!\n", 6537088Swollman inet_ntoa(isaddr)); 654128645Sluigi goto drop; 6551541Srgrimes } 656136441Srwatson /* 657136441Srwatson * Warn if another host is using the same IP address, but only if the 658136441Srwatson * IP address isn't 0.0.0.0, which is used for DHCP only, in which 659136441Srwatson * case we suppress the warning to avoid false positive complaints of 660136441Srwatson * potential misconfiguration. 661136441Srwatson */ 662150942Sthompsa if (!bridged && isaddr.s_addr == myaddr.s_addr && myaddr.s_addr != 0) { 6631541Srgrimes log(LOG_ERR, 664174256Syar "arp: %*D is using my IP address %s on %s!\n", 66584931Sfjoe ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 666174256Syar inet_ntoa(isaddr), ifp->if_xname); 6671541Srgrimes itaddr = myaddr; 668196797Sgnn ARPSTAT_INC(dupips); 6691541Srgrimes goto reply; 6701541Srgrimes } 671120626Sru if (ifp->if_flags & IFF_STATICARP) 672120626Sru goto reply; 673148955Sglebius 674186119Sqingli bzero(&sin, sizeof(sin)); 675186119Sqingli sin.sin_len = sizeof(struct sockaddr_in); 676186119Sqingli sin.sin_family = AF_INET; 677186119Sqingli sin.sin_addr = isaddr; 678186119Sqingli flags = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0; 679186119Sqingli flags |= LLE_EXCLUSIVE; 680186119Sqingli IF_AFDATA_LOCK(ifp); 681186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin); 682186119Sqingli IF_AFDATA_UNLOCK(ifp); 683186119Sqingli if (la != NULL) { 684186119Sqingli /* the following is not an error when doing bridging */ 685211157Swill if (!bridged && la->lle_tbl->llt_ifp != ifp && !carp_match) { 686186119Sqingli if (log_arp_wrong_iface) 687227785Sglebius log(LOG_WARNING, "arp: %s is on %s " 688186119Sqingli "but got reply from %*D on %s\n", 689186119Sqingli inet_ntoa(isaddr), 690186119Sqingli la->lle_tbl->llt_ifp->if_xname, 691186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 692186119Sqingli ifp->if_xname); 693196738Sbz LLE_WUNLOCK(la); 694186119Sqingli goto reply; 695186119Sqingli } 696186119Sqingli if ((la->la_flags & LLE_VALID) && 697186119Sqingli bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { 698186119Sqingli if (la->la_flags & LLE_STATIC) { 699196738Sbz LLE_WUNLOCK(la); 700223840Sae if (log_arp_permanent_modify) 701223840Sae log(LOG_ERR, 702223840Sae "arp: %*D attempts to modify " 703223840Sae "permanent entry for %s on %s\n", 704223840Sae ifp->if_addrlen, 705223840Sae (u_char *)ar_sha(ah), ":", 706223840Sae inet_ntoa(isaddr), ifp->if_xname); 707186119Sqingli goto reply; 708178888Sjulian } 709186119Sqingli if (log_arp_movements) { 710186119Sqingli log(LOG_INFO, "arp: %s moved from %*D " 711186119Sqingli "to %*D on %s\n", 712186119Sqingli inet_ntoa(isaddr), 713186119Sqingli ifp->if_addrlen, 714186119Sqingli (u_char *)&la->ll_addr, ":", 715186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 716186119Sqingli ifp->if_xname); 717178888Sjulian } 718178888Sjulian } 719186119Sqingli 720186119Sqingli if (ifp->if_addrlen != ah->ar_hln) { 721196738Sbz LLE_WUNLOCK(la); 722227785Sglebius log(LOG_WARNING, "arp from %*D: addr len: new %d, " 723227785Sglebius "i/f %d (ignored)\n", ifp->if_addrlen, 724227785Sglebius (u_char *) ar_sha(ah), ":", ah->ar_hln, 725227785Sglebius ifp->if_addrlen); 726217315Sgnn goto drop; 727178888Sjulian } 728186119Sqingli (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); 729186119Sqingli la->la_flags |= LLE_VALID; 730178888Sjulian 731196995Snp EVENTHANDLER_INVOKE(arp_update_event, la); 732196995Snp 733186119Sqingli if (!(la->la_flags & LLE_STATIC)) { 734206481Sbz int canceled; 735206481Sbz 736206481Sbz LLE_ADDREF(la); 737216075Sglebius la->la_expire = time_uptime + V_arpt_keep; 738206481Sbz canceled = callout_reset(&la->la_timer, 739206481Sbz hz * V_arpt_keep, arptimer, la); 740206481Sbz if (canceled) 741206481Sbz LLE_REMREF(la); 74239389Sfenner } 743178888Sjulian la->la_asked = 0; 744181803Sbz la->la_preempt = V_arp_maxtries; 745215207Sgnn /* 746215207Sgnn * The packets are all freed within the call to the output 747215207Sgnn * routine. 748215207Sgnn * 749215207Sgnn * NB: The lock MUST be released before the call to the 750215207Sgnn * output routine. 751215207Sgnn */ 752215207Sgnn if (la->la_hold != NULL) { 753215207Sgnn struct mbuf *m_hold, *m_hold_next; 754215207Sgnn 755217113Sgnn m_hold = la->la_hold; 756217113Sgnn la->la_hold = NULL; 757217113Sgnn la->la_numheld = 0; 758186119Sqingli memcpy(&sa, L3_ADDR(la), sizeof(sa)); 759215207Sgnn LLE_WUNLOCK(la); 760217121Sgnn for (; m_hold != NULL; m_hold = m_hold_next) { 761215207Sgnn m_hold_next = m_hold->m_nextpkt; 762215207Sgnn m_hold->m_nextpkt = NULL; 763215207Sgnn (*ifp->if_output)(ifp, m_hold, &sa, NULL); 764215207Sgnn } 765215207Sgnn } else 766215207Sgnn LLE_WUNLOCK(la); 767223261Sbz } 768178888Sjulianreply: 769128645Sluigi if (op != ARPOP_REQUEST) 770128645Sluigi goto drop; 771196797Sgnn ARPSTAT_INC(rxrequests); 772186119Sqingli 7731541Srgrimes if (itaddr.s_addr == myaddr.s_addr) { 774178888Sjulian /* Shortcut.. the receiving interface is the target. */ 77584931Sfjoe (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 776142215Sglebius (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 7771541Srgrimes } else { 778186317Sqingli struct llentry *lle = NULL; 7793282Swollman 780186317Sqingli sin.sin_addr = itaddr; 781197225Sqingli IF_AFDATA_LOCK(ifp); 782197225Sqingli lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin); 783197225Sqingli IF_AFDATA_UNLOCK(ifp); 784186317Sqingli 785197225Sqingli if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { 786186317Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 787186317Sqingli (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); 788186317Sqingli LLE_RUNLOCK(lle); 789197225Sqingli } else { 79063080Sdwmalone 791197225Sqingli if (lle != NULL) 792197225Sqingli LLE_RUNLOCK(lle); 793186317Sqingli 794197225Sqingli if (!V_arp_proxyall) 795197225Sqingli goto drop; 796197225Sqingli 797197225Sqingli sin.sin_addr = itaddr; 798197225Sqingli /* XXX MRT use table 0 for arp reply */ 799197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 800197225Sqingli if (!rt) 801197225Sqingli goto drop; 802197225Sqingli 803197225Sqingli /* 804197225Sqingli * Don't send proxies for nodes on the same interface 805197225Sqingli * as this one came out of, or we'll get into a fight 806197225Sqingli * over who claims what Ether address. 807197225Sqingli */ 808197225Sqingli if (!rt->rt_ifp || rt->rt_ifp == ifp) { 809197225Sqingli RTFREE_LOCKED(rt); 810197225Sqingli goto drop; 811197225Sqingli } 812185713Scsjp RTFREE_LOCKED(rt); 81363080Sdwmalone 814197225Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 815197225Sqingli (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 816197225Sqingli 817197225Sqingli /* 818197225Sqingli * Also check that the node which sent the ARP packet 819218909Sbrucec * is on the interface we expect it to be on. This 820197225Sqingli * avoids ARP chaos if an interface is connected to the 821197225Sqingli * wrong network. 822197225Sqingli */ 823197225Sqingli sin.sin_addr = isaddr; 824197225Sqingli 825197225Sqingli /* XXX MRT use table 0 for arp checks */ 826197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 827197225Sqingli if (!rt) 828197225Sqingli goto drop; 829197225Sqingli if (rt->rt_ifp != ifp) { 830197225Sqingli log(LOG_INFO, "arp_proxy: ignoring request" 831197225Sqingli " from %s via %s, expecting %s\n", 832197225Sqingli inet_ntoa(isaddr), ifp->if_xname, 833197225Sqingli rt->rt_ifp->if_xname); 834197225Sqingli RTFREE_LOCKED(rt); 835197225Sqingli goto drop; 836197225Sqingli } 837197225Sqingli RTFREE_LOCKED(rt); 838197225Sqingli 8394069Swollman#ifdef DEBUG_PROXY 840197225Sqingli printf("arp: proxying for %s\n", 841197225Sqingli inet_ntoa(itaddr)); 8424069Swollman#endif 843197225Sqingli } 8441541Srgrimes } 8451541Srgrimes 846166436Sbms if (itaddr.s_addr == myaddr.s_addr && 847166436Sbms IN_LINKLOCAL(ntohl(itaddr.s_addr))) { 848166436Sbms /* RFC 3927 link-local IPv4; always reply by broadcast. */ 849166436Sbms#ifdef DEBUG_LINKLOCAL 850166436Sbms printf("arp: sending reply for link-local addr %s\n", 851166436Sbms inet_ntoa(itaddr)); 852166436Sbms#endif 853166436Sbms m->m_flags |= M_BCAST; 854166436Sbms m->m_flags &= ~M_MCAST; 855166436Sbms } else { 856166436Sbms /* default behaviour; never reply by broadcast. */ 857166436Sbms m->m_flags &= ~(M_BCAST|M_MCAST); 858166436Sbms } 85984931Sfjoe (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); 86084931Sfjoe (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 86184931Sfjoe ah->ar_op = htons(ARPOP_REPLY); 86284931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 863127261Smdodd m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 864127261Smdodd m->m_pkthdr.len = m->m_len; 865223753Sae m->m_pkthdr.rcvif = NULL; 866127261Smdodd sa.sa_family = AF_ARP; 867127261Smdodd sa.sa_len = 2; 868191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 869196797Sgnn ARPSTAT_INC(txreplies); 8701541Srgrimes return; 871128645Sluigi 872128645Sluigidrop: 873128645Sluigi m_freem(m); 8741541Srgrimes} 87532350Seivind#endif 8761541Srgrimes 8775195Swollmanvoid 878169454Srwatsonarp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) 8795195Swollman{ 880186119Sqingli struct llentry *lle; 881186119Sqingli 882186411Sqingli if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) { 88384931Sfjoe arprequest(ifp, &IA_SIN(ifa)->sin_addr, 88484931Sfjoe &IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp)); 885186411Sqingli /* 886186411Sqingli * interface address is considered static entry 887186411Sqingli * because the output of the arp utility shows 888186411Sqingli * that L2 entry as permanent 889186411Sqingli */ 890186411Sqingli IF_AFDATA_LOCK(ifp); 891186411Sqingli lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC), 892186411Sqingli (struct sockaddr *)IA_SIN(ifa)); 893186411Sqingli IF_AFDATA_UNLOCK(ifp); 894186411Sqingli if (lle == NULL) 895186411Sqingli log(LOG_INFO, "arp_ifinit: cannot create arp " 896186411Sqingli "entry for interface address\n"); 897186411Sqingli else 898186411Sqingli LLE_RUNLOCK(lle); 899186411Sqingli } 900186119Sqingli ifa->ifa_rtrequest = NULL; 9015195Swollman} 90269152Sjlemon 903142215Sglebiusvoid 904169454Srwatsonarp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr) 905142215Sglebius{ 906142215Sglebius if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) 907142215Sglebius arprequest(ifp, &IA_SIN(ifa)->sin_addr, 908142215Sglebius &IA_SIN(ifa)->sin_addr, enaddr); 909186119Sqingli ifa->ifa_rtrequest = NULL; 910142215Sglebius} 911142215Sglebius 912190787Szecstatic void 913190787Szecarp_init(void) 914190787Szec{ 915190787Szec 916193219Srwatson netisr_register(&arp_nh); 91769152Sjlemon} 91869152SjlemonSYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); 919