| From 92f7dae00bf70b0ae76f016fa3af6a71b2b5f748 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 31 Mar 2022 10:26:43 +0300 |
| Subject: vrf: fix packet sniffing for traffic originating from ip tunnels |
| |
| From: Eyal Birger <eyal.birger@gmail.com> |
| |
| [ Upstream commit 012d69fbfcc739f846766c1da56ef8b493b803b5 ] |
| |
| in commit 048939088220 |
| ("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: 048939088220 ("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> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/vrf.c | 15 +++++++++++---- |
| 1 file changed, 11 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c |
| index b2242a082431..091dd7caf10c 100644 |
| --- a/drivers/net/vrf.c |
| +++ b/drivers/net/vrf.c |
| @@ -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. |
| @@ -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); |
| @@ -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; |
| @@ -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); |
| @@ -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; |
| @@ -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); |
| -- |
| 2.35.1 |
| |