From: Tomasz Dzieciol <tomasz.dziec...@nokia.com> Fix an issue where is_garp variable is not set when arp_accept option is disabled for a net device. There might be a situation where gratuitous ARP will be ignored when an existing neighbour is updated in a time smaller than LOCKTIME (for example by a timer - transition between states).
Signed-off-by: Tomasz Dzieciol <tomasz.dziec...@nokia.com> --- net/ipv4/arp.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 51b27ae..9fd23c9 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -641,6 +641,13 @@ void arp_xmit(struct sk_buff *skb) } EXPORT_SYMBOL(arp_xmit); +static inline bool arp_is_gratuitous(unsigned int addr_type, + int op, __be32 sip, __be32 tip) +{ + return op == ARPOP_REQUEST && tip == sip && + addr_type == RTN_UNICAST; +} + /* * Process an arp request. */ @@ -836,19 +843,30 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) n = __neigh_lookup(&arp_tbl, &sip, dev, 0); if (IN_DEV_ARP_ACCEPT(in_dev)) { - unsigned int addr_type = inet_addr_type_dev_table(net, dev, sip); + unsigned int addr_type = inet_addr_type_dev_table(net, + dev, sip); /* Unsolicited ARP is not accepted by default. 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 && - addr_type == RTN_UNICAST; + is_garp = arp_is_gratuitous(addr_type, ntohs(arp->ar_op), + sip, tip); if (!n && ((arp->ar_op == htons(ARPOP_REPLY) && addr_type == RTN_UNICAST) || is_garp)) n = __neigh_lookup(&arp_tbl, &sip, dev, 1); + } else if (n) { + unsigned int addr_type = inet_addr_type_dev_table(net, + dev, sip); + + /* If the ARP table already contains the IP address of the + gratuitous arp frame, the arp table will be updated + regardless if this setting is on or off. + */ + is_garp = arp_is_gratuitous(addr_type, ntohs(arp->ar_op), + sip, tip); } if (n) { -- 2.5.0