aboutsummaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
authorSalam Noureddine <noureddine@aristanetworks.com>2013-12-24 14:17:02 -0800
committerMoyster <oysterized@gmail.com>2019-05-02 14:30:26 +0200
commit92807c917fd2dc3a4b2038176716e8fe31dc4514 (patch)
tree25045b95ba8df05d3eec26927ce7c59c7cd0726e /net/ipv4
parent30a6caf5e2ec75b9e23e8f1be3c76be819e1b371 (diff)
ipv4: arp: update neighbour address when a gratuitous arp is received and arp_accept is set
Gratuitous arp packets are useful in switchover scenarios to update client arp tables as quickly as possible. Currently, the mac address of a neighbour is only updated after a locktime period has elapsed since the last update. In most use cases such delays are unacceptable for network admins. Moreover, the "updated" field of the neighbour stucture doesn't record the last time the address of a neighbour changed but records any change that happens to the neighbour. This is clearly a bug since locktime uses that field as meaning "addr_updated". With this observation, I was able to perpetuate a stale address by sending a stream of gratuitous arp packets spaced less than locktime apart. With this change the address is updated when a gratuitous arp is received and the arp_accept sysctl is set. Change-Id: Ic902dec99749684ab82527d15e0beed2bbaa1c77 Signed-off-by: Salam Noureddine <noureddine@aristanetworks.com> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/arp.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index d0ee14d6a..3473def87 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -732,6 +732,7 @@ static int arp_process(struct sk_buff *skb)
int addr_type;
struct neighbour *n;
struct net *net = dev_net(dev);
+ bool is_garp = false;
/* arp_rcv below verifies the ARP header and verifies the device
* is ARP'able.
@@ -906,10 +907,12 @@ static int arp_process(struct sk_buff *skb)
It is possible, that this option should be enabled for some
devices (strip is candidate)
*/
+ is_garp = arp->ar_op == htons(ARPOP_REQUEST) && tip == sip &&
+ inet_addr_type(net, sip) == RTN_UNICAST;
+
if (n == NULL &&
- (arp->ar_op == htons(ARPOP_REPLY) ||
- (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) &&
- inet_addr_type(net, sip) == RTN_UNICAST)
+ ((arp->ar_op == htons(ARPOP_REPLY) &&
+ inet_addr_type(net, sip) == RTN_UNICAST) || is_garp))
n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
}
@@ -922,7 +925,10 @@ static int arp_process(struct sk_buff *skb)
agents are active. Taking the first reply prevents
arp trashing and chooses the fastest router.
*/
- override = time_after(jiffies, n->updated + n->parms->locktime);
+ override = time_after(jiffies,
+ n->updated +
+ n->parms->locktime) ||
+ is_garp;
/* Broadcast replies and request packets
do not assert neighbour reachability.