If a socket was created with socket(AF_PACKET, SOCK_RAW, 0), the
protocol number is unavailable. Try to ask the driver to extract it from
the L2 header in order for skb_try_probe_transport_header to succeed.

Signed-off-by: Maxim Mikityanskiy <maxi...@mellanox.com>
---
 net/packet/af_packet.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8fc76e68777a..d1d89749a17a 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1850,6 +1850,15 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct 
net_device *dev,
        return 0;
 }
 
+static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
+{
+       if (!skb->protocol && sock->type == SOCK_RAW) {
+               skb_reset_mac_header(skb);
+               skb->protocol = dev_parse_header_protocol(skb);
+       }
+
+       skb_try_probe_transport_header(skb);
+}
 
 /*
  *     Output a raw packet to a device layer. This bypasses all the other
@@ -1970,7 +1979,7 @@ static int packet_sendmsg_spkt(struct socket *sock, 
struct msghdr *msg,
        if (unlikely(extra_len == 4))
                skb->no_fcs = 1;
 
-       skb_try_probe_transport_header(skb);
+       packet_parse_headers(skb, sock);
 
        dev_queue_xmit(skb);
        rcu_read_unlock();
@@ -2519,7 +2528,7 @@ static int tpacket_fill_skb(struct packet_sock *po, 
struct sk_buff *skb,
                len = ((to_write > len_max) ? len_max : to_write);
        }
 
-       skb_try_probe_transport_header(skb);
+       packet_parse_headers(skb, sock);
 
        return tp_len;
 }
@@ -2924,7 +2933,7 @@ static int packet_snd(struct socket *sock, struct msghdr 
*msg, size_t len)
                virtio_net_hdr_set_proto(skb, &vnet_hdr);
        }
 
-       skb_try_probe_transport_header(skb);
+       packet_parse_headers(skb, sock);
 
        if (unlikely(extra_len == 4))
                skb->no_fcs = 1;
-- 
2.19.1

Reply via email to