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$"); 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> 67230442Sbz#ifdef INET 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 76249925Sglebius#define SIN(s) ((const 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; 90238945Sglebiusstatic VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for 91238945Sglebius * 20 seconds */ 92253084SaeVNET_PCPUSTAT_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */ 93253084SaeVNET_PCPUSTAT_SYSINIT(arpstat); 941541Srgrimes 95253084Sae#ifdef VIMAGE 96253084SaeVNET_PCPUSTAT_SYSUNINIT(arpstat); 97253084Sae#endif /* VIMAGE */ 98253084Sae 99215701Sdimstatic VNET_DEFINE(int, arp_maxhold) = 1; 100215207Sgnn 101195727Srwatson#define V_arpt_keep VNET(arpt_keep) 102198111Sqingli#define V_arpt_down VNET(arpt_down) 103195727Srwatson#define V_arp_maxtries VNET(arp_maxtries) 104195727Srwatson#define V_arp_proxyall VNET(arp_proxyall) 105215207Sgnn#define V_arp_maxhold VNET(arp_maxhold) 10612693Sphk 107195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, 108195699Srwatson &VNET_NAME(arpt_keep), 0, 109195699Srwatson "ARP entry lifetime in seconds"); 110195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, 111195699Srwatson &VNET_NAME(arp_maxtries), 0, 112183550Szec "ARP resolution attempts before returning error"); 113195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW, 114195699Srwatson &VNET_NAME(useloopback), 0, 115183550Szec "Use the loopback interface for local traffic"); 116195699SrwatsonSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, 117195699Srwatson &VNET_NAME(arp_proxyall), 0, 118183550Szec "Enable proxy ARP for all suitable requests"); 119215207SgnnSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, wait, CTLFLAG_RW, 120215207Sgnn &VNET_NAME(arpt_down), 0, 121215207Sgnn "Incomplete ARP entry lifetime in seconds"); 122253084SaeSYSCTL_VNET_PCPUSTAT(_net_link_ether_arp, OID_AUTO, stats, struct arpstat, 123253084Sae arpstat, "ARP statistics (struct arpstat, net/if_arp.h)"); 124215207SgnnSYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxhold, CTLFLAG_RW, 125238945Sglebius &VNET_NAME(arp_maxhold), 0, 126215207Sgnn "Number of packets to hold per ARP entry"); 12712693Sphk 12892723Salfredstatic void arp_init(void); 129111888Sjlemonstatic void arpintr(struct mbuf *); 13092723Salfredstatic void arptimer(void *); 13132350Seivind#ifdef INET 13292723Salfredstatic void in_arpinput(struct mbuf *); 13332350Seivind#endif 13412693Sphk 135193219Srwatsonstatic const struct netisr_handler arp_nh = { 136193219Srwatson .nh_name = "arp", 137193219Srwatson .nh_handler = arpintr, 138193219Srwatson .nh_proto = NETISR_ARP, 139193219Srwatson .nh_policy = NETISR_POLICY_SOURCE, 140193219Srwatson}; 141193219Srwatson 142186119Sqingli#ifdef AF_INET 1431541Srgrimes/* 144186119Sqingli * called by in_ifscrub to remove entry from the table when 145186119Sqingli * the interface goes away 1461541Srgrimes */ 147186119Sqinglivoid 148186119Sqingliarp_ifscrub(struct ifnet *ifp, uint32_t addr) 1491541Srgrimes{ 150186119Sqingli struct sockaddr_in addr4; 1511541Srgrimes 152186119Sqingli bzero((void *)&addr4, sizeof(addr4)); 153186119Sqingli addr4.sin_len = sizeof(addr4); 154186119Sqingli addr4.sin_family = AF_INET; 155186119Sqingli addr4.sin_addr.s_addr = addr; 156186119Sqingli IF_AFDATA_LOCK(ifp); 157186119Sqingli lla_lookup(LLTABLE(ifp), (LLE_DELETE | LLE_IFADDR), 158186119Sqingli (struct sockaddr *)&addr4); 159186119Sqingli IF_AFDATA_UNLOCK(ifp); 1601541Srgrimes} 161186119Sqingli#endif 1621541Srgrimes 1631541Srgrimes/* 164186119Sqingli * Timeout routine. Age arp_tab entries periodically. 1651541Srgrimes */ 1665196Swollmanstatic void 167186119Sqingliarptimer(void *arg) 1681541Srgrimes{ 169238990Sglebius struct llentry *lle = (struct llentry *)arg; 170186119Sqingli struct ifnet *ifp; 1711541Srgrimes 172238990Sglebius if (lle->la_flags & LLE_STATIC) { 173238990Sglebius LLE_WUNLOCK(lle); 174238990Sglebius return; 175238990Sglebius } 176238990Sglebius 177186119Sqingli ifp = lle->lle_tbl->llt_ifp; 178196797Sgnn CURVNET_SET(ifp->if_vnet); 179238990Sglebius 180252577Snp if ((lle->la_flags & LLE_DELETED) == 0) { 181238990Sglebius int evt; 182238990Sglebius 183238990Sglebius if (lle->la_flags & LLE_VALID) 184238990Sglebius evt = LLENTRY_EXPIRED; 185238990Sglebius else 186238990Sglebius evt = LLENTRY_TIMEDOUT; 187238990Sglebius EVENTHANDLER_INVOKE(lle_event, lle, evt); 188238990Sglebius } 189238990Sglebius 190238990Sglebius callout_stop(&lle->la_timer); 191238990Sglebius 192238990Sglebius /* XXX: LOR avoidance. We still have ref on lle. */ 193238990Sglebius LLE_WUNLOCK(lle); 194186119Sqingli IF_AFDATA_LOCK(ifp); 195186119Sqingli LLE_WLOCK(lle); 196237263Snp 197244183Sglebius /* Guard against race with other llentry_free(). */ 198244183Sglebius if (lle->la_flags & LLE_LINKED) { 199244183Sglebius size_t pkts_dropped; 200244183Sglebius 201244183Sglebius LLE_REMREF(lle); 202244183Sglebius pkts_dropped = llentry_free(lle); 203244183Sglebius ARPSTAT_ADD(dropped, pkts_dropped); 204244183Sglebius } else 205244183Sglebius LLE_FREE_LOCKED(lle); 206244183Sglebius 207186119Sqingli IF_AFDATA_UNLOCK(ifp); 208244183Sglebius 209238990Sglebius ARPSTAT_INC(timeouts); 210244183Sglebius 211196797Sgnn CURVNET_RESTORE(); 2121541Srgrimes} 2131541Srgrimes 2141541Srgrimes/* 2151541Srgrimes * Broadcast an ARP request. Caller specifies: 2161541Srgrimes * - arp header source ip address 2171541Srgrimes * - arp header target ip address 2181541Srgrimes * - arp header source ethernet address 2191541Srgrimes */ 220186119Sqinglivoid 221249925Sglebiusarprequest(struct ifnet *ifp, const struct in_addr *sip, 222249925Sglebius const struct in_addr *tip, u_char *enaddr) 2231541Srgrimes{ 224126936Smdodd struct mbuf *m; 225126936Smdodd struct arphdr *ah; 2261541Srgrimes struct sockaddr sa; 227229816Sglebius u_char *carpaddr = NULL; 2281541Srgrimes 229186119Sqingli if (sip == NULL) { 230186119Sqingli /* 231186119Sqingli * The caller did not supply a source address, try to find 232186119Sqingli * a compatible one among those assigned to this interface. 233186119Sqingli */ 234186119Sqingli struct ifaddr *ifa; 235186119Sqingli 236229816Sglebius IF_ADDR_RLOCK(ifp); 237186119Sqingli TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 238229816Sglebius if (ifa->ifa_addr->sa_family != AF_INET) 239186119Sqingli continue; 240229816Sglebius 241229816Sglebius if (ifa->ifa_carp) { 242229816Sglebius if ((*carp_iamatch_p)(ifa, &carpaddr) == 0) 243229816Sglebius continue; 244229816Sglebius sip = &IA_SIN(ifa)->sin_addr; 245229816Sglebius } else { 246229816Sglebius carpaddr = NULL; 247229816Sglebius sip = &IA_SIN(ifa)->sin_addr; 248229816Sglebius } 249229816Sglebius 250186119Sqingli if (0 == ((sip->s_addr ^ tip->s_addr) & 251229816Sglebius IA_MASKSIN(ifa)->sin_addr.s_addr)) 252186119Sqingli break; /* found it. */ 253186119Sqingli } 254229816Sglebius IF_ADDR_RUNLOCK(ifp); 255238945Sglebius if (sip == NULL) { 256186119Sqingli printf("%s: cannot find matching address\n", __func__); 257186119Sqingli return; 258186119Sqingli } 259186119Sqingli } 260229816Sglebius if (enaddr == NULL) 261229816Sglebius enaddr = carpaddr ? carpaddr : (u_char *)IF_LLADDR(ifp); 262186119Sqingli 263243882Sglebius if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) 2641541Srgrimes return; 265127261Smdodd m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) + 266127261Smdodd 2*ifp->if_data.ifi_addrlen; 267127277Smdodd m->m_pkthdr.len = m->m_len; 268127277Smdodd MH_ALIGN(m, m->m_len); 269127277Smdodd ah = mtod(m, struct arphdr *); 270127261Smdodd bzero((caddr_t)ah, m->m_len); 271101090Srwatson#ifdef MAC 272173095Srwatson mac_netinet_arp_send(ifp, m); 273101090Srwatson#endif 27484931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); 27584931Sfjoe ah->ar_hln = ifp->if_addrlen; /* hardware address length */ 27684931Sfjoe ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ 27784931Sfjoe ah->ar_op = htons(ARPOP_REQUEST); 278249925Sglebius bcopy(enaddr, ar_sha(ah), ah->ar_hln); 279249925Sglebius bcopy(sip, ar_spa(ah), ah->ar_pln); 280249925Sglebius bcopy(tip, ar_tpa(ah), ah->ar_pln); 281127261Smdodd sa.sa_family = AF_ARP; 282127261Smdodd sa.sa_len = 2; 283127261Smdodd m->m_flags |= M_BCAST; 284254523Sandre m_clrprotoflags(m); /* Avoid confusing lower layers. */ 285191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 286196797Sgnn ARPSTAT_INC(txrequests); 2871541Srgrimes} 2881541Srgrimes 2891541Srgrimes/* 290128636Sluigi * Resolve an IP address into an ethernet address. 291128636Sluigi * On input: 292128636Sluigi * ifp is the interface we use 293175025Sjulian * rt0 is the route to the final destination (possibly useless) 294175025Sjulian * m is the mbuf. May be NULL if we don't have a packet. 295128636Sluigi * dst is the next hop, 296128636Sluigi * desten is where we want the address. 297128636Sluigi * 298128636Sluigi * On success, desten is filled in and the function returns 0; 299128636Sluigi * If the packet must be held pending resolution, we return EWOULDBLOCK 300128636Sluigi * On other errors, we return the corresponding error code. 301175025Sjulian * Note that m_freem() handles NULL. 3021541Srgrimes */ 3031541Srgrimesint 304128636Sluigiarpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, 305249925Sglebius const struct sockaddr *dst, u_char *desten, struct llentry **lle) 3061541Srgrimes{ 307186119Sqingli struct llentry *la = 0; 308186200Skmacy u_int flags = 0; 309215207Sgnn struct mbuf *curr = NULL; 310215207Sgnn struct mbuf *next = NULL; 311186119Sqingli int error, renew; 3121541Srgrimes 313186119Sqingli *lle = NULL; 314186119Sqingli if (m != NULL) { 315175025Sjulian if (m->m_flags & M_BCAST) { 316175025Sjulian /* broadcast */ 317175025Sjulian (void)memcpy(desten, 318175025Sjulian ifp->if_broadcastaddr, ifp->if_addrlen); 319175025Sjulian return (0); 320175025Sjulian } 321175025Sjulian if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) { 322175025Sjulian /* multicast */ 323175025Sjulian ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); 324175025Sjulian return (0); 325175025Sjulian } 3261541Srgrimes } 327186119Sqingliretry: 328238967Sglebius IF_AFDATA_RLOCK(ifp); 329186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, dst); 330238967Sglebius IF_AFDATA_RUNLOCK(ifp); 331186200Skmacy if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0) 332238967Sglebius && ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0)) { 333186200Skmacy flags |= (LLE_CREATE | LLE_EXCLUSIVE); 334238967Sglebius IF_AFDATA_WLOCK(ifp); 335186200Skmacy la = lla_lookup(LLTABLE(ifp), flags, dst); 336238967Sglebius IF_AFDATA_WUNLOCK(ifp); 337186200Skmacy } 338148955Sglebius if (la == NULL) { 339186119Sqingli if (flags & LLE_CREATE) 340148955Sglebius log(LOG_DEBUG, 341148955Sglebius "arpresolve: can't allocate llinfo for %s\n", 342148955Sglebius inet_ntoa(SIN(dst)->sin_addr)); 343186119Sqingli m_freem(m); 344186119Sqingli return (EINVAL); 345238945Sglebius } 346149909Sglebius 347186119Sqingli if ((la->la_flags & LLE_VALID) && 348216075Sglebius ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { 349186119Sqingli bcopy(&la->ll_addr, desten, ifp->if_addrlen); 35092802Sorion /* 35192802Sorion * If entry has an expiry time and it is approaching, 352186119Sqingli * see if we need to send an ARP request within this 353186119Sqingli * arpt_down interval. 35492802Sorion */ 355186119Sqingli if (!(la->la_flags & LLE_STATIC) && 356216075Sglebius time_uptime + la->la_preempt > la->la_expire) { 357229816Sglebius arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); 358110544Sorion la->la_preempt--; 359186119Sqingli } 360238967Sglebius 361186119Sqingli *lle = la; 362186119Sqingli error = 0; 363186119Sqingli goto done; 364238945Sglebius } 365238945Sglebius 366186119Sqingli if (la->la_flags & LLE_STATIC) { /* should not happen! */ 367186119Sqingli log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", 368186119Sqingli inet_ntoa(SIN(dst)->sin_addr)); 369186119Sqingli m_freem(m); 370186119Sqingli error = EINVAL; 371186119Sqingli goto done; 372186119Sqingli } 37392802Sorion 374216075Sglebius renew = (la->la_asked == 0 || la->la_expire != time_uptime); 375186119Sqingli if ((renew || m != NULL) && (flags & LLE_EXCLUSIVE) == 0) { 376186119Sqingli flags |= LLE_EXCLUSIVE; 377186119Sqingli LLE_RUNLOCK(la); 378186119Sqingli goto retry; 3791541Srgrimes } 3801541Srgrimes /* 3811541Srgrimes * There is an arptab entry, but no ethernet address 382215207Sgnn * response yet. Add the mbuf to the list, dropping 383215207Sgnn * the oldest packet if we have exceeded the system 384215207Sgnn * setting. 3851541Srgrimes */ 386186119Sqingli if (m != NULL) { 387215207Sgnn if (la->la_numheld >= V_arp_maxhold) { 388215207Sgnn if (la->la_hold != NULL) { 389215207Sgnn next = la->la_hold->m_nextpkt; 390215207Sgnn m_freem(la->la_hold); 391215207Sgnn la->la_hold = next; 392215207Sgnn la->la_numheld--; 393215207Sgnn ARPSTAT_INC(dropped); 394215207Sgnn } 395238945Sglebius } 396196797Sgnn if (la->la_hold != NULL) { 397215207Sgnn curr = la->la_hold; 398215207Sgnn while (curr->m_nextpkt != NULL) 399215207Sgnn curr = curr->m_nextpkt; 400215207Sgnn curr->m_nextpkt = m; 401238945Sglebius } else 402215207Sgnn la->la_hold = m; 403215207Sgnn la->la_numheld++; 404186119Sqingli if (renew == 0 && (flags & LLE_EXCLUSIVE)) { 405186119Sqingli flags &= ~LLE_EXCLUSIVE; 406186119Sqingli LLE_DOWNGRADE(la); 407186119Sqingli } 408238967Sglebius 409174699Skmacy } 410152188Sglebius /* 411152188Sglebius * Return EWOULDBLOCK if we have tried less than arp_maxtries. It 412152188Sglebius * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH 413152188Sglebius * if we have already sent arp_maxtries ARP requests. Retransmit the 414152188Sglebius * ARP request, but not faster than one request per second. 415152188Sglebius */ 416181803Sbz if (la->la_asked < V_arp_maxtries) 417152188Sglebius error = EWOULDBLOCK; /* First request. */ 418152188Sglebius else 419201416Snp error = rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) ? 420201416Snp EHOSTUNREACH : EHOSTDOWN; 421152188Sglebius 422186119Sqingli if (renew) { 423206481Sbz int canceled; 424206481Sbz 425186119Sqingli LLE_ADDREF(la); 426216075Sglebius la->la_expire = time_uptime; 427206481Sbz canceled = callout_reset(&la->la_timer, hz * V_arpt_down, 428206481Sbz arptimer, la); 429206481Sbz if (canceled) 430206481Sbz LLE_REMREF(la); 431166010Smaxim la->la_asked++; 432186119Sqingli LLE_WUNLOCK(la); 433229816Sglebius arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); 434186119Sqingli return (error); 435186119Sqingli } 436186119Sqinglidone: 437186119Sqingli if (flags & LLE_EXCLUSIVE) 438186119Sqingli LLE_WUNLOCK(la); 439186119Sqingli else 440186119Sqingli LLE_RUNLOCK(la); 441152188Sglebius return (error); 4421541Srgrimes} 4431541Srgrimes 4441541Srgrimes/* 4451541Srgrimes * Common length and type checks are done here, 4461541Srgrimes * then the protocol-specific routine is called. 4471541Srgrimes */ 44812693Sphkstatic void 449111888Sjlemonarpintr(struct mbuf *m) 4501541Srgrimes{ 451111888Sjlemon struct arphdr *ar; 4521541Srgrimes 453111888Sjlemon if (m->m_len < sizeof(struct arphdr) && 454111888Sjlemon ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) { 455227785Sglebius log(LOG_NOTICE, "arp: runt packet -- m_pullup failed\n"); 456111888Sjlemon return; 457111888Sjlemon } 458111888Sjlemon ar = mtod(m, struct arphdr *); 4591541Srgrimes 460111888Sjlemon if (ntohs(ar->ar_hrd) != ARPHRD_ETHER && 461111888Sjlemon ntohs(ar->ar_hrd) != ARPHRD_IEEE802 && 462130407Sdfr ntohs(ar->ar_hrd) != ARPHRD_ARCNET && 463219819Sjeff ntohs(ar->ar_hrd) != ARPHRD_IEEE1394 && 464219819Sjeff ntohs(ar->ar_hrd) != ARPHRD_INFINIBAND) { 465227790Sglebius log(LOG_NOTICE, "arp: unknown hardware address format (0x%2D)" 466227790Sglebius " (from %*D to %*D)\n", (unsigned char *)&ar->ar_hrd, "", 467227790Sglebius ETHER_ADDR_LEN, (u_char *)ar_sha(ar), ":", 468227790Sglebius ETHER_ADDR_LEN, (u_char *)ar_tha(ar), ":"); 469111888Sjlemon m_freem(m); 470111888Sjlemon return; 471111888Sjlemon } 4721541Srgrimes 473123768Sru if (m->m_len < arphdr_len(ar)) { 474123765Sru if ((m = m_pullup(m, arphdr_len(ar))) == NULL) { 475227785Sglebius log(LOG_NOTICE, "arp: runt packet\n"); 476123765Sru m_freem(m); 477123765Sru return; 478123765Sru } 479123765Sru ar = mtod(m, struct arphdr *); 480111888Sjlemon } 48157900Srwatson 482196797Sgnn ARPSTAT_INC(received); 483111888Sjlemon switch (ntohs(ar->ar_pro)) { 48432350Seivind#ifdef INET 485111888Sjlemon case ETHERTYPE_IP: 486111888Sjlemon in_arpinput(m); 487111888Sjlemon return; 48832350Seivind#endif 4891541Srgrimes } 490111888Sjlemon m_freem(m); 4911541Srgrimes} 4921541Srgrimes 49332350Seivind#ifdef INET 4941541Srgrimes/* 4951541Srgrimes * ARP for Internet protocols on 10 Mb/s Ethernet. 4961541Srgrimes * Algorithm is that given in RFC 826. 4971541Srgrimes * In addition, a sanity check is performed on the sender 4981541Srgrimes * protocol address, to catch impersonators. 4991541Srgrimes * We no longer handle negotiations for use of trailer protocol: 5001541Srgrimes * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent 5011541Srgrimes * along with IP replies if we wanted trailers sent to us, 5021541Srgrimes * and also sent them in response to IP replies. 5031541Srgrimes * This allowed either end to announce the desire to receive 5041541Srgrimes * trailer packets. 5051541Srgrimes * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, 5061541Srgrimes * but formerly didn't normally send requests. 5071541Srgrimes */ 50870699Salfredstatic int log_arp_wrong_iface = 1; 50982893Salfredstatic int log_arp_movements = 1; 510153513Sglebiusstatic int log_arp_permanent_modify = 1; 511240073Sglebiusstatic int allow_multicast = 0; 512250504Sglebiusstatic struct timeval arp_lastlog; 513250504Sglebiusstatic int arp_curpps; 514250504Sglebiusstatic int arp_maxpps = 1; 51570699Salfred 51670699SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW, 51770699Salfred &log_arp_wrong_iface, 0, 51870699Salfred "log arp packets arriving on the wrong interface"); 51982893SalfredSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_movements, CTLFLAG_RW, 520238945Sglebius &log_arp_movements, 0, 521238945Sglebius "log arp replies from MACs different than the one in the cache"); 522153513SglebiusSYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_permanent_modify, CTLFLAG_RW, 523238945Sglebius &log_arp_permanent_modify, 0, 524238945Sglebius "log arp replies from MACs different than the one in the permanent arp entry"); 525240073SglebiusSYSCTL_INT(_net_link_ether_inet, OID_AUTO, allow_multicast, CTLFLAG_RW, 526240073Sglebius &allow_multicast, 0, "accept multicast addresses"); 527250504SglebiusSYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_log_per_second, 528250504Sglebius CTLFLAG_RW, &arp_maxpps, 0, 529250504Sglebius "Maximum number of remotely triggered ARP messages that can be " 530250504Sglebius "logged per second"); 53170699Salfred 532250504Sglebius#define ARP_LOG(pri, ...) do { \ 533250504Sglebius if (ppsratecheck(&arp_lastlog, &arp_curpps, arp_maxpps)) \ 534250504Sglebius log((pri), "arp: " __VA_ARGS__); \ 535250504Sglebius} while (0) 536250504Sglebius 5371541Srgrimesstatic void 538169454Srwatsonin_arpinput(struct mbuf *m) 5391541Srgrimes{ 540126936Smdodd struct arphdr *ah; 541126936Smdodd struct ifnet *ifp = m->m_pkthdr.rcvif; 542186119Sqingli struct llentry *la = NULL; 543126936Smdodd struct rtentry *rt; 54484102Sjlemon struct ifaddr *ifa; 54584102Sjlemon struct in_ifaddr *ia; 5461541Srgrimes struct sockaddr sa; 5471541Srgrimes struct in_addr isaddr, itaddr, myaddr; 548142215Sglebius u_int8_t *enaddr = NULL; 549186119Sqingli int op, flags; 55084931Sfjoe int req_len; 551181824Sphilip int bridged = 0, is_bridge = 0; 552228571Sglebius int carped; 553174559Skmacy struct sockaddr_in sin; 554174559Skmacy sin.sin_len = sizeof(struct sockaddr_in); 555174559Skmacy sin.sin_family = AF_INET; 556174703Skmacy sin.sin_addr.s_addr = 0; 557183550Szec 558155018Sthompsa if (ifp->if_bridge) 559146986Sthompsa bridged = 1; 560181824Sphilip if (ifp->if_type == IFT_BRIDGE) 561181824Sphilip is_bridge = 1; 562146986Sthompsa 56384931Sfjoe req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr)); 56484931Sfjoe if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) { 565250504Sglebius ARP_LOG(LOG_NOTICE, "runt packet -- m_pullup failed\n"); 56674851Syar return; 56774851Syar } 56874851Syar 56984931Sfjoe ah = mtod(m, struct arphdr *); 570238945Sglebius /* 571217315Sgnn * ARP is only for IPv4 so we can reject packets with 572217315Sgnn * a protocol length not equal to an IPv4 address. 573217315Sgnn */ 574217315Sgnn if (ah->ar_pln != sizeof(struct in_addr)) { 575250504Sglebius ARP_LOG(LOG_NOTICE, "requested protocol length != %zu\n", 576217315Sgnn sizeof(struct in_addr)); 577249903Sglebius goto drop; 578217315Sgnn } 579217315Sgnn 580240073Sglebius if (allow_multicast == 0 && ETHER_IS_MULTICAST(ar_sha(ah))) { 581250504Sglebius ARP_LOG(LOG_NOTICE, "%*D is multicast\n", 582227785Sglebius ifp->if_addrlen, (u_char *)ar_sha(ah), ":"); 583249903Sglebius goto drop; 584217315Sgnn } 585217315Sgnn 58684931Sfjoe op = ntohs(ah->ar_op); 58784931Sfjoe (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); 58884931Sfjoe (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); 589134991Sglebius 590196797Sgnn if (op == ARPOP_REPLY) 591196797Sgnn ARPSTAT_INC(rxreplies); 592196797Sgnn 59384102Sjlemon /* 59484102Sjlemon * For a bridge, we want to check the address irrespective 59584102Sjlemon * of the receive interface. (This will change slightly 59684102Sjlemon * when we have clusters of interfaces). 59784102Sjlemon */ 598194951Srwatson IN_IFADDR_RLOCK(); 599143314Sglebius LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 600217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 601186119Sqingli ia->ia_ifp == ifp) && 602228571Sglebius itaddr.s_addr == ia->ia_addr.sin_addr.s_addr && 603228571Sglebius (ia->ia_ifa.ifa_carp == NULL || 604228571Sglebius (*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) { 605194820Srwatson ifa_ref(&ia->ia_ifa); 606194951Srwatson IN_IFADDR_RUNLOCK(); 607143314Sglebius goto match; 608194820Srwatson } 609143314Sglebius } 61084102Sjlemon LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) 611217829Sthompsa if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || 612186119Sqingli ia->ia_ifp == ifp) && 613194820Srwatson isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { 614194820Srwatson ifa_ref(&ia->ia_ifa); 615194951Srwatson IN_IFADDR_RUNLOCK(); 61684102Sjlemon goto match; 617194820Srwatson } 618181824Sphilip 619181824Sphilip#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ 620181824Sphilip (ia->ia_ifp->if_bridge == ifp->if_softc && \ 621181824Sphilip !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ 622181824Sphilip addr == ia->ia_addr.sin_addr.s_addr) 62384102Sjlemon /* 624181824Sphilip * Check the case when bridge shares its MAC address with 625181824Sphilip * some of its children, so packets are claimed by bridge 626181824Sphilip * itself (bridge_input() does it first), but they are really 627181824Sphilip * meant to be destined to the bridge member. 628181824Sphilip */ 629181824Sphilip if (is_bridge) { 630181824Sphilip LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { 631181824Sphilip if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { 632194820Srwatson ifa_ref(&ia->ia_ifa); 633181824Sphilip ifp = ia->ia_ifp; 634194951Srwatson IN_IFADDR_RUNLOCK(); 635181824Sphilip goto match; 636181824Sphilip } 637181824Sphilip } 638181824Sphilip } 639181824Sphilip#undef BDG_MEMBER_MATCHES_ARP 640194951Srwatson IN_IFADDR_RUNLOCK(); 641181824Sphilip 642181824Sphilip /* 64385223Sjlemon * No match, use the first inet address on the receive interface 64484102Sjlemon * as a dummy address for the rest of the function. 64584102Sjlemon */ 646229621Sjhb IF_ADDR_RLOCK(ifp); 64785223Sjlemon TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 648228959Sglebius if (ifa->ifa_addr->sa_family == AF_INET && 649228959Sglebius (ifa->ifa_carp == NULL || 650228959Sglebius (*carp_iamatch_p)(ifa, &enaddr))) { 65185466Sjlemon ia = ifatoia(ifa); 652194820Srwatson ifa_ref(ifa); 653229621Sjhb IF_ADDR_RUNLOCK(ifp); 65485466Sjlemon goto match; 65585466Sjlemon } 656229621Sjhb IF_ADDR_RUNLOCK(ifp); 657194820Srwatson 65885466Sjlemon /* 65985466Sjlemon * If bridging, fall back to using any inet address. 66085466Sjlemon */ 661194951Srwatson IN_IFADDR_RLOCK(); 662194951Srwatson if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) { 663194951Srwatson IN_IFADDR_RUNLOCK(); 664128645Sluigi goto drop; 665194951Srwatson } 666194820Srwatson ifa_ref(&ia->ia_ifa); 667194951Srwatson IN_IFADDR_RUNLOCK(); 66884102Sjlemonmatch: 669142215Sglebius if (!enaddr) 670142215Sglebius enaddr = (u_int8_t *)IF_LLADDR(ifp); 671228571Sglebius carped = (ia->ia_ifa.ifa_carp != NULL); 67284102Sjlemon myaddr = ia->ia_addr.sin_addr; 673194820Srwatson ifa_free(&ia->ia_ifa); 674142215Sglebius if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) 675128645Sluigi goto drop; /* it's from me, ignore it. */ 67684931Sfjoe if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { 677250504Sglebius ARP_LOG(LOG_NOTICE, "link address is broadcast for IP address " 678250504Sglebius "%s!\n", inet_ntoa(isaddr)); 679128645Sluigi goto drop; 6801541Srgrimes } 681136441Srwatson /* 682136441Srwatson * Warn if another host is using the same IP address, but only if the 683136441Srwatson * IP address isn't 0.0.0.0, which is used for DHCP only, in which 684136441Srwatson * case we suppress the warning to avoid false positive complaints of 685136441Srwatson * potential misconfiguration. 686136441Srwatson */ 687228571Sglebius if (!bridged && !carped && isaddr.s_addr == myaddr.s_addr && 688228571Sglebius myaddr.s_addr != 0) { 689250504Sglebius ARP_LOG(LOG_ERR, "%*D is using my IP address %s on %s!\n", 69084931Sfjoe ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 691174256Syar inet_ntoa(isaddr), ifp->if_xname); 6921541Srgrimes itaddr = myaddr; 693196797Sgnn ARPSTAT_INC(dupips); 6941541Srgrimes goto reply; 6951541Srgrimes } 696120626Sru if (ifp->if_flags & IFF_STATICARP) 697120626Sru goto reply; 698148955Sglebius 699186119Sqingli bzero(&sin, sizeof(sin)); 700186119Sqingli sin.sin_len = sizeof(struct sockaddr_in); 701186119Sqingli sin.sin_family = AF_INET; 702186119Sqingli sin.sin_addr = isaddr; 703186119Sqingli flags = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0; 704186119Sqingli flags |= LLE_EXCLUSIVE; 705238945Sglebius IF_AFDATA_LOCK(ifp); 706186119Sqingli la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin); 707186119Sqingli IF_AFDATA_UNLOCK(ifp); 708186119Sqingli if (la != NULL) { 709186119Sqingli /* the following is not an error when doing bridging */ 710228571Sglebius if (!bridged && la->lle_tbl->llt_ifp != ifp) { 711186119Sqingli if (log_arp_wrong_iface) 712250504Sglebius ARP_LOG(LOG_WARNING, "%s is on %s " 713186119Sqingli "but got reply from %*D on %s\n", 714186119Sqingli inet_ntoa(isaddr), 715186119Sqingli la->lle_tbl->llt_ifp->if_xname, 716186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 717186119Sqingli ifp->if_xname); 718196738Sbz LLE_WUNLOCK(la); 719186119Sqingli goto reply; 720186119Sqingli } 721186119Sqingli if ((la->la_flags & LLE_VALID) && 722186119Sqingli bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { 723186119Sqingli if (la->la_flags & LLE_STATIC) { 724196738Sbz LLE_WUNLOCK(la); 725223840Sae if (log_arp_permanent_modify) 726250504Sglebius ARP_LOG(LOG_ERR, 727250504Sglebius "%*D attempts to modify " 728223840Sae "permanent entry for %s on %s\n", 729223840Sae ifp->if_addrlen, 730223840Sae (u_char *)ar_sha(ah), ":", 731223840Sae inet_ntoa(isaddr), ifp->if_xname); 732186119Sqingli goto reply; 733178888Sjulian } 734186119Sqingli if (log_arp_movements) { 735250504Sglebius ARP_LOG(LOG_INFO, "%s moved from %*D " 736186119Sqingli "to %*D on %s\n", 737186119Sqingli inet_ntoa(isaddr), 738186119Sqingli ifp->if_addrlen, 739186119Sqingli (u_char *)&la->ll_addr, ":", 740186119Sqingli ifp->if_addrlen, (u_char *)ar_sha(ah), ":", 741186119Sqingli ifp->if_xname); 742178888Sjulian } 743178888Sjulian } 744238945Sglebius 745186119Sqingli if (ifp->if_addrlen != ah->ar_hln) { 746196738Sbz LLE_WUNLOCK(la); 747250504Sglebius ARP_LOG(LOG_WARNING, "from %*D: addr len: new %d, " 748227785Sglebius "i/f %d (ignored)\n", ifp->if_addrlen, 749227785Sglebius (u_char *) ar_sha(ah), ":", ah->ar_hln, 750227785Sglebius ifp->if_addrlen); 751217315Sgnn goto drop; 752178888Sjulian } 753186119Sqingli (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); 754186119Sqingli la->la_flags |= LLE_VALID; 755178888Sjulian 756237263Snp EVENTHANDLER_INVOKE(lle_event, la, LLENTRY_RESOLVED); 757196995Snp 758186119Sqingli if (!(la->la_flags & LLE_STATIC)) { 759206481Sbz int canceled; 760206481Sbz 761206481Sbz LLE_ADDREF(la); 762216075Sglebius la->la_expire = time_uptime + V_arpt_keep; 763206481Sbz canceled = callout_reset(&la->la_timer, 764206481Sbz hz * V_arpt_keep, arptimer, la); 765206481Sbz if (canceled) 766206481Sbz LLE_REMREF(la); 76739389Sfenner } 768178888Sjulian la->la_asked = 0; 769181803Sbz la->la_preempt = V_arp_maxtries; 770238945Sglebius /* 771215207Sgnn * The packets are all freed within the call to the output 772215207Sgnn * routine. 773215207Sgnn * 774215207Sgnn * NB: The lock MUST be released before the call to the 775215207Sgnn * output routine. 776215207Sgnn */ 777215207Sgnn if (la->la_hold != NULL) { 778215207Sgnn struct mbuf *m_hold, *m_hold_next; 779215207Sgnn 780217113Sgnn m_hold = la->la_hold; 781217113Sgnn la->la_hold = NULL; 782217113Sgnn la->la_numheld = 0; 783186119Sqingli memcpy(&sa, L3_ADDR(la), sizeof(sa)); 784215207Sgnn LLE_WUNLOCK(la); 785217121Sgnn for (; m_hold != NULL; m_hold = m_hold_next) { 786215207Sgnn m_hold_next = m_hold->m_nextpkt; 787215207Sgnn m_hold->m_nextpkt = NULL; 788254523Sandre /* Avoid confusing lower layers. */ 789254523Sandre m_clrprotoflags(m_hold); 790215207Sgnn (*ifp->if_output)(ifp, m_hold, &sa, NULL); 791215207Sgnn } 792215207Sgnn } else 793215207Sgnn LLE_WUNLOCK(la); 794223261Sbz } 795178888Sjulianreply: 796128645Sluigi if (op != ARPOP_REQUEST) 797128645Sluigi goto drop; 798196797Sgnn ARPSTAT_INC(rxrequests); 799186119Sqingli 8001541Srgrimes if (itaddr.s_addr == myaddr.s_addr) { 801178888Sjulian /* Shortcut.. the receiving interface is the target. */ 80284931Sfjoe (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 803142215Sglebius (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 8041541Srgrimes } else { 805186317Sqingli struct llentry *lle = NULL; 8063282Swollman 807186317Sqingli sin.sin_addr = itaddr; 808238945Sglebius IF_AFDATA_LOCK(ifp); 809197225Sqingli lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin); 810197225Sqingli IF_AFDATA_UNLOCK(ifp); 811186317Sqingli 812197225Sqingli if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { 813186317Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 814186317Sqingli (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); 815186317Sqingli LLE_RUNLOCK(lle); 816197225Sqingli } else { 81763080Sdwmalone 818197225Sqingli if (lle != NULL) 819197225Sqingli LLE_RUNLOCK(lle); 820186317Sqingli 821197225Sqingli if (!V_arp_proxyall) 822197225Sqingli goto drop; 823238967Sglebius 824197225Sqingli sin.sin_addr = itaddr; 825197225Sqingli /* XXX MRT use table 0 for arp reply */ 826197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 827197225Sqingli if (!rt) 828197225Sqingli goto drop; 829197225Sqingli 830197225Sqingli /* 831197225Sqingli * Don't send proxies for nodes on the same interface 832197225Sqingli * as this one came out of, or we'll get into a fight 833197225Sqingli * over who claims what Ether address. 834197225Sqingli */ 835197225Sqingli if (!rt->rt_ifp || rt->rt_ifp == ifp) { 836197225Sqingli RTFREE_LOCKED(rt); 837197225Sqingli goto drop; 838197225Sqingli } 839185713Scsjp RTFREE_LOCKED(rt); 84063080Sdwmalone 841197225Sqingli (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 842197225Sqingli (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); 843197225Sqingli 844197225Sqingli /* 845197225Sqingli * Also check that the node which sent the ARP packet 846218909Sbrucec * is on the interface we expect it to be on. This 847197225Sqingli * avoids ARP chaos if an interface is connected to the 848197225Sqingli * wrong network. 849197225Sqingli */ 850197225Sqingli sin.sin_addr = isaddr; 851238967Sglebius 852197225Sqingli /* XXX MRT use table 0 for arp checks */ 853197225Sqingli rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); 854197225Sqingli if (!rt) 855197225Sqingli goto drop; 856197225Sqingli if (rt->rt_ifp != ifp) { 857250504Sglebius ARP_LOG(LOG_INFO, "proxy: ignoring request" 858197225Sqingli " from %s via %s, expecting %s\n", 859197225Sqingli inet_ntoa(isaddr), ifp->if_xname, 860197225Sqingli rt->rt_ifp->if_xname); 861197225Sqingli RTFREE_LOCKED(rt); 862197225Sqingli goto drop; 863197225Sqingli } 864197225Sqingli RTFREE_LOCKED(rt); 865197225Sqingli 8664069Swollman#ifdef DEBUG_PROXY 867238945Sglebius printf("arp: proxying for %s\n", inet_ntoa(itaddr)); 8684069Swollman#endif 869197225Sqingli } 8701541Srgrimes } 8711541Srgrimes 872166436Sbms if (itaddr.s_addr == myaddr.s_addr && 873166436Sbms IN_LINKLOCAL(ntohl(itaddr.s_addr))) { 874166436Sbms /* RFC 3927 link-local IPv4; always reply by broadcast. */ 875166436Sbms#ifdef DEBUG_LINKLOCAL 876166436Sbms printf("arp: sending reply for link-local addr %s\n", 877166436Sbms inet_ntoa(itaddr)); 878166436Sbms#endif 879166436Sbms m->m_flags |= M_BCAST; 880166436Sbms m->m_flags &= ~M_MCAST; 881166436Sbms } else { 882166436Sbms /* default behaviour; never reply by broadcast. */ 883166436Sbms m->m_flags &= ~(M_BCAST|M_MCAST); 884166436Sbms } 88584931Sfjoe (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); 88684931Sfjoe (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); 88784931Sfjoe ah->ar_op = htons(ARPOP_REPLY); 88884931Sfjoe ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ 889238945Sglebius m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); 890238945Sglebius m->m_pkthdr.len = m->m_len; 891223753Sae m->m_pkthdr.rcvif = NULL; 892127261Smdodd sa.sa_family = AF_ARP; 893127261Smdodd sa.sa_len = 2; 894254523Sandre m_clrprotoflags(m); /* Avoid confusing lower layers. */ 895191148Skmacy (*ifp->if_output)(ifp, m, &sa, NULL); 896196797Sgnn ARPSTAT_INC(txreplies); 8971541Srgrimes return; 898128645Sluigi 899128645Sluigidrop: 900128645Sluigi m_freem(m); 9011541Srgrimes} 90232350Seivind#endif 9031541Srgrimes 9045195Swollmanvoid 905169454Srwatsonarp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) 9065195Swollman{ 907186119Sqingli struct llentry *lle; 908186119Sqingli 909228571Sglebius if (ifa->ifa_carp != NULL) 910228571Sglebius return; 911228571Sglebius 912186411Sqingli if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) { 91384931Sfjoe arprequest(ifp, &IA_SIN(ifa)->sin_addr, 91484931Sfjoe &IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp)); 915238945Sglebius /* 916186411Sqingli * interface address is considered static entry 917186411Sqingli * because the output of the arp utility shows 918186411Sqingli * that L2 entry as permanent 919186411Sqingli */ 920186411Sqingli IF_AFDATA_LOCK(ifp); 921186411Sqingli lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC), 922186411Sqingli (struct sockaddr *)IA_SIN(ifa)); 923186411Sqingli IF_AFDATA_UNLOCK(ifp); 924186411Sqingli if (lle == NULL) 925186411Sqingli log(LOG_INFO, "arp_ifinit: cannot create arp " 926186411Sqingli "entry for interface address\n"); 927186411Sqingli else 928186411Sqingli LLE_RUNLOCK(lle); 929186411Sqingli } 930186119Sqingli ifa->ifa_rtrequest = NULL; 9315195Swollman} 93269152Sjlemon 933142215Sglebiusvoid 934169454Srwatsonarp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr) 935142215Sglebius{ 936142215Sglebius if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) 937142215Sglebius arprequest(ifp, &IA_SIN(ifa)->sin_addr, 938142215Sglebius &IA_SIN(ifa)->sin_addr, enaddr); 939186119Sqingli ifa->ifa_rtrequest = NULL; 940142215Sglebius} 941142215Sglebius 942190787Szecstatic void 943190787Szecarp_init(void) 944190787Szec{ 945190787Szec 946193219Srwatson netisr_register(&arp_nh); 94769152Sjlemon} 94869152SjlemonSYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); 949