Skip to content

Commit

Permalink
vrf: fix packet sniffing for traffic originating from ip tunnels
Browse files Browse the repository at this point in the history
in commit 0489390
("vrf: add mac header for tunneled packets when sniffer is attached")
an Ethernet header was cooked for traffic originating from tunnel devices.

However, the header is added based on whether the mac_header is unset
and ignores cases where the device doesn't expose a mac header to upper
layers, such as in ip tunnels like ipip and gre.

Traffic originating from such devices still appears garbled when capturing
on the vrf device.

Fix by observing whether the original device exposes a header to upper
layers, similar to the logic done in af_packet.

In addition, skb->mac_len needs to be adjusted after adding the Ethernet
header for the skb_push/pull() surrounding dev_queue_xmit_nit() to work
on these packets.

Fixes: 0489390 ("vrf: add mac header for tunneled packets when sniffer is attached")
Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eyal Birger authored and David S. Miller committed Apr 1, 2022
1 parent 9381fe8 commit 012d69f
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions drivers/net/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,7 @@ static int vrf_prepare_mac_header(struct sk_buff *skb,
eth = (struct ethhdr *)skb->data;

skb_reset_mac_header(skb);
skb_reset_mac_len(skb);

/* we set the ethernet destination and the source addresses to the
* address of the VRF device.
Expand Down Expand Up @@ -1294,9 +1295,9 @@ static int vrf_prepare_mac_header(struct sk_buff *skb,
*/
static int vrf_add_mac_header_if_unset(struct sk_buff *skb,
struct net_device *vrf_dev,
u16 proto)
u16 proto, struct net_device *orig_dev)
{
if (skb_mac_header_was_set(skb))
if (skb_mac_header_was_set(skb) && dev_has_header(orig_dev))
return 0;

return vrf_prepare_mac_header(skb, vrf_dev, proto);
Expand Down Expand Up @@ -1402,6 +1403,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,

/* if packet is NDISC then keep the ingress interface */
if (!is_ndisc) {
struct net_device *orig_dev = skb->dev;

vrf_rx_stats(vrf_dev, skb->len);
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
Expand All @@ -1410,7 +1413,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
int err;

err = vrf_add_mac_header_if_unset(skb, vrf_dev,
ETH_P_IPV6);
ETH_P_IPV6,
orig_dev);
if (likely(!err)) {
skb_push(skb, skb->mac_len);
dev_queue_xmit_nit(skb, vrf_dev);
Expand Down Expand Up @@ -1440,6 +1444,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
struct sk_buff *skb)
{
struct net_device *orig_dev = skb->dev;

skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
IPCB(skb)->flags |= IPSKB_L3SLAVE;
Expand All @@ -1460,7 +1466,8 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
if (!list_empty(&vrf_dev->ptype_all)) {
int err;

err = vrf_add_mac_header_if_unset(skb, vrf_dev, ETH_P_IP);
err = vrf_add_mac_header_if_unset(skb, vrf_dev, ETH_P_IP,
orig_dev);
if (likely(!err)) {
skb_push(skb, skb->mac_len);
dev_queue_xmit_nit(skb, vrf_dev);
Expand Down

0 comments on commit 012d69f

Please sign in to comment.