aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/arp.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index ca6e1e6c1496..c22103cec823 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -641,12 +641,12 @@ void arp_xmit(struct sk_buff *skb)
641} 641}
642EXPORT_SYMBOL(arp_xmit); 642EXPORT_SYMBOL(arp_xmit);
643 643
644static bool arp_is_garp(struct net_device *dev, int addr_type, 644static bool arp_is_garp(struct net *net, struct net_device *dev,
645 __be16 ar_op, 645 int *addr_type, __be16 ar_op,
646 __be32 sip, __be32 tip, 646 __be32 sip, __be32 tip,
647 unsigned char *sha, unsigned char *tha) 647 unsigned char *sha, unsigned char *tha)
648{ 648{
649 bool is_garp = tip == sip && addr_type == RTN_UNICAST; 649 bool is_garp = tip == sip;
650 650
651 /* Gratuitous ARP _replies_ also require target hwaddr to be 651 /* Gratuitous ARP _replies_ also require target hwaddr to be
652 * the same as source. 652 * the same as source.
@@ -659,6 +659,11 @@ static bool arp_is_garp(struct net_device *dev, int addr_type,
659 tha && 659 tha &&
660 !memcmp(tha, sha, dev->addr_len); 660 !memcmp(tha, sha, dev->addr_len);
661 661
662 if (is_garp) {
663 *addr_type = inet_addr_type_dev_table(net, dev, sip);
664 if (*addr_type != RTN_UNICAST)
665 is_garp = false;
666 }
662 return is_garp; 667 return is_garp;
663} 668}
664 669
@@ -859,18 +864,23 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
859 n = __neigh_lookup(&arp_tbl, &sip, dev, 0); 864 n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
860 865
861 if (IN_DEV_ARP_ACCEPT(in_dev)) { 866 if (IN_DEV_ARP_ACCEPT(in_dev)) {
862 unsigned int addr_type = inet_addr_type_dev_table(net, dev, sip); 867 addr_type = -1;
863 868
864 /* Unsolicited ARP is not accepted by default. 869 /* Unsolicited ARP is not accepted by default.
865 It is possible, that this option should be enabled for some 870 It is possible, that this option should be enabled for some
866 devices (strip is candidate) 871 devices (strip is candidate)
867 */ 872 */
868 is_garp = arp_is_garp(dev, addr_type, arp->ar_op, 873 is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
869 sip, tip, sha, tha); 874 sip, tip, sha, tha);
870 875
871 if (!n && 876 if (!n &&
872 ((arp->ar_op == htons(ARPOP_REPLY) && 877 (is_garp ||
873 addr_type == RTN_UNICAST) || is_garp)) 878 (arp->ar_op == htons(ARPOP_REPLY) &&
879 (addr_type == RTN_UNICAST ||
880 (addr_type < 0 &&
881 /* postpone calculation to as late as possible */
882 inet_addr_type_dev_table(net, dev, sip) ==
883 RTN_UNICAST)))))
874 n = __neigh_lookup(&arp_tbl, &sip, dev, 1); 884 n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
875 } 885 }
876 886