diff options
author | Marco Pfatschbacher <mpf@cvs.openbsd.org> | 2009-10-17 12:20:18 +0000 |
---|---|---|
committer | Marco Pfatschbacher <mpf@cvs.openbsd.org> | 2009-10-17 12:20:18 +0000 |
commit | f335696f647d11ae642752ff8f7e8a07a37cd2ee (patch) | |
tree | cb62e520fec733809f6620a0e6721175dfcb743a | |
parent | d54685b17e3d73c139ae2817167ce43e8eb288df (diff) |
Allow us to accept gratuitous ARP requests in cases where the
link-route points over the carp interface. (IP-less carpdev)
The descision whether to drop an ARP query is now expressed with
a goto out; rather than a second check later, which prevented
the carpdev case to work. Also add some comments to make
in_arpinput() easier to understand.
OK henning, markus.
-rw-r--r-- | sys/netinet/if_ether.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index cd814028cee..f347efc8cb1 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ether.c,v 1.80 2009/06/05 00:05:22 claudio Exp $ */ +/* $OpenBSD: if_ether.c,v 1.81 2009/10/17 12:20:17 mpf Exp $ */ /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ /* @@ -601,6 +601,7 @@ in_arpinput(m) bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof(itaddr)); bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof(isaddr)); + /* First try: check target against our addresses */ TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { if (itaddr.s_addr != ia->ia_addr.sin_addr.s_addr) continue; @@ -609,11 +610,15 @@ in_arpinput(m) if (ia->ia_ifp->if_type == IFT_CARP && ((ia->ia_ifp->if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))) { - if (ia->ia_ifp == m->m_pkthdr.rcvif && - (op == ARPOP_REPLY || - carp_iamatch(ia, ea->arp_sha, - &enaddr, ðer_shost))) - break; + if (ia->ia_ifp == m->m_pkthdr.rcvif) { + if (op == ARPOP_REPLY) + break; + if (carp_iamatch(ia, ea->arp_sha, + &enaddr, ðer_shost)) + break; + else + goto out; + } } else #endif if (ia->ia_ifp == m->m_pkthdr.rcvif) @@ -633,22 +638,27 @@ in_arpinput(m) #if NCARP > 0 else if (ia->ia_ifp->if_carpdev != NULL && m->m_pkthdr.rcvif->if_bridge == - ia->ia_ifp->if_carpdev->if_bridge && - carp_iamatch(ia, ea->arp_sha, - &enaddr, ðer_shost)) - bridge_ia = ia; + ia->ia_ifp->if_carpdev->if_bridge) { + if (carp_iamatch(ia, ea->arp_sha, + &enaddr, ðer_shost)) + bridge_ia = ia; + else + goto out; + } #endif } #endif } #if NBRIDGE > 0 + /* use bridge_ia if there was no direct match */ if (ia == NULL && bridge_ia != NULL) { ia = bridge_ia; ac = (struct arpcom *)bridge_ia->ia_ifp; } #endif + /* Second try: check source against our addresses */ if (ia == NULL) { TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { if (isaddr.s_addr != ia->ia_addr.sin_addr.s_addr) @@ -658,7 +668,8 @@ in_arpinput(m) } } - if (ia == NULL && m->m_pkthdr.rcvif->if_type != IFT_CARP) { + /* Third try: not one of our addresses, just find an usable ia */ + if (ia == NULL) { struct ifaddr *ifa; TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrlist, ifa_list) { @@ -706,12 +717,14 @@ in_arpinput(m) ac->ac_if.if_xname); goto out; } else if (rt->rt_ifp != &ac->ac_if) { - log(LOG_WARNING, - "arp: attempt to overwrite entry for %s " - "on %s by %s on %s\n", - inet_ntoa(isaddr), rt->rt_ifp->if_xname, - ether_sprintf(ea->arp_sha), - ac->ac_if.if_xname); + if (ac->ac_if.if_type != IFT_CARP) + log(LOG_WARNING, + "arp: attempt to overwrite entry for" + " %s on %s by %s on %s\n", + inet_ntoa(isaddr), + rt->rt_ifp->if_xname, + ether_sprintf(ea->arp_sha), + ac->ac_if.if_xname); goto out; } else { log(LOG_INFO, @@ -766,7 +779,7 @@ in_arpinput(m) } reply: if (op != ARPOP_REQUEST) { - out: +out: m_freem(m); return; } |