arp: Inherit metadata dst when creating ARP requests
authorThomas Graf <tgraf@suug.ch>
Tue, 21 Jul 2015 08:43:57 +0000 (10:43 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jul 2015 17:39:05 +0000 (10:39 -0700)
If output device wants to see the dst, inherit the dst of the
original skb and pass it on to generate the ARP request.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/arp.c

index 933a92820d265e07b8c42300c7be6742565723b5..1d59e50ce8b744d299a3556d36db7e5571826cd5 100644 (file)
@@ -291,6 +291,40 @@ static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb)
        kfree_skb(skb);
 }
 
+/* Create and send an arp packet. */
+static void arp_send_dst(int type, int ptype, __be32 dest_ip,
+                        struct net_device *dev, __be32 src_ip,
+                        const unsigned char *dest_hw,
+                        const unsigned char *src_hw,
+                        const unsigned char *target_hw, struct sk_buff *oskb)
+{
+       struct sk_buff *skb;
+
+       /* arp on this interface. */
+       if (dev->flags & IFF_NOARP)
+               return;
+
+       skb = arp_create(type, ptype, dest_ip, dev, src_ip,
+                        dest_hw, src_hw, target_hw);
+       if (!skb)
+               return;
+
+       if (oskb)
+               skb_dst_copy(skb, oskb);
+
+       arp_xmit(skb);
+}
+
+void arp_send(int type, int ptype, __be32 dest_ip,
+             struct net_device *dev, __be32 src_ip,
+             const unsigned char *dest_hw, const unsigned char *src_hw,
+             const unsigned char *target_hw)
+{
+       arp_send_dst(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw,
+                    target_hw, NULL);
+}
+EXPORT_SYMBOL(arp_send);
+
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
        __be32 saddr = 0;
@@ -346,8 +380,9 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
                }
        }
 
-       arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
-                dst_hw, dev->dev_addr, NULL);
+       arp_send_dst(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
+                    dst_hw, dev->dev_addr, NULL,
+                    dev->priv_flags & IFF_XMIT_DST_RELEASE ? NULL : skb);
 }
 
 static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
@@ -596,32 +631,6 @@ void arp_xmit(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(arp_xmit);
 
-/*
- *     Create and send an arp packet.
- */
-void arp_send(int type, int ptype, __be32 dest_ip,
-             struct net_device *dev, __be32 src_ip,
-             const unsigned char *dest_hw, const unsigned char *src_hw,
-             const unsigned char *target_hw)
-{
-       struct sk_buff *skb;
-
-       /*
-        *      No arp on this interface.
-        */
-
-       if (dev->flags&IFF_NOARP)
-               return;
-
-       skb = arp_create(type, ptype, dest_ip, dev, src_ip,
-                        dest_hw, src_hw, target_hw);
-       if (!skb)
-               return;
-
-       arp_xmit(skb);
-}
-EXPORT_SYMBOL(arp_send);
-
 /*
  *     Process an arp request.
  */