]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/ipv4/arp.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux.git] / net / ipv4 / arp.c
index 0937b34c27cacb2dec73a67a76ff11fe26722500..d54345a06f720fb1cd7632a364aa7e7e19ff6216 100644 (file)
@@ -653,6 +653,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
        unsigned char *arp_ptr;
        struct rtable *rt;
        unsigned char *sha;
+       unsigned char *tha = NULL;
        __be32 sip, tip;
        u16 dev_type = dev->type;
        int addr_type;
@@ -724,6 +725,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
                break;
 #endif
        default:
+               tha = arp_ptr;
                arp_ptr += dev->addr_len;
        }
        memcpy(&tip, arp_ptr, 4);
@@ -842,8 +844,18 @@ static int arp_process(struct net *net, struct sock *sk, 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 &&
-                         addr_type == RTN_UNICAST;
+               is_garp = tip == sip && addr_type == RTN_UNICAST;
+
+               /* Unsolicited ARP _replies_ also require target hwaddr to be
+                * the same as source.
+                */
+               if (is_garp && arp->ar_op == htons(ARPOP_REPLY))
+                       is_garp =
+                               /* IPv4 over IEEE 1394 doesn't provide target
+                                * hardware address field in its ARP payload.
+                                */
+                               tha &&
+                               !memcmp(tha, sha, dev->addr_len);
 
                if (!n &&
                    ((arp->ar_op == htons(ARPOP_REPLY)  &&