|
@@ -1203,6 +1203,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
|
|
|
bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
|
|
|
struct sk_buff *skb, int hdr_size)
|
|
|
{
|
|
|
+ struct batadv_dat_entry *dat_entry = NULL;
|
|
|
u16 type;
|
|
|
__be32 ip_src, ip_dst;
|
|
|
u8 *hw_src, *hw_dst;
|
|
@@ -1225,12 +1226,41 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
|
|
|
hw_dst = batadv_arp_hw_dst(skb, hdr_size);
|
|
|
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
|
|
|
|
|
|
+ /* If ip_dst is already in cache and has the right mac address,
|
|
|
+ * drop this frame if this ARP reply is destined for us because it's
|
|
|
+ * most probably an ARP reply generated by another node of the DHT.
|
|
|
+ * We have most probably received already a reply earlier. Delivering
|
|
|
+ * this frame would lead to doubled receive of an ARP reply.
|
|
|
+ */
|
|
|
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_src, vid);
|
|
|
+ if (dat_entry && batadv_compare_eth(hw_src, dat_entry->mac_addr)) {
|
|
|
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "Doubled ARP reply removed: ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]; dat_entry: %pM-%pI4\n",
|
|
|
+ hw_src, &ip_src, hw_dst, &ip_dst,
|
|
|
+ dat_entry->mac_addr, &dat_entry->ip);
|
|
|
+ dropped = true;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
/* Update our internal cache with both the IP addresses the node got
|
|
|
* within the ARP reply
|
|
|
*/
|
|
|
batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
|
|
|
batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
|
|
|
|
|
|
+ /* If BLA is enabled, only forward ARP replies if we have claimed the
|
|
|
+ * source of the ARP reply or if no one else of the same backbone has
|
|
|
+ * already claimed that client. This prevents that different gateways
|
|
|
+ * to the same backbone all forward the ARP reply leading to multiple
|
|
|
+ * replies in the backbone.
|
|
|
+ */
|
|
|
+ if (!batadv_bla_check_claim(bat_priv, hw_src, vid)) {
|
|
|
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
|
|
|
+ "Device %pM claimed by another backbone gw. Drop ARP reply.\n",
|
|
|
+ hw_src);
|
|
|
+ dropped = true;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
/* if this REPLY is directed to a client of mine, let's deliver the
|
|
|
* packet to the interface
|
|
|
*/
|
|
@@ -1243,6 +1273,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
|
|
|
out:
|
|
|
if (dropped)
|
|
|
kfree_skb(skb);
|
|
|
+ if (dat_entry)
|
|
|
+ batadv_dat_entry_put(dat_entry);
|
|
|
/* if dropped == false -> deliver to the interface */
|
|
|
return dropped;
|
|
|
}
|