net/packet: Ask driver for protocol if not provided by user
authorMaxim Mikityanskiy <maximmi@mellanox.com>
Thu, 21 Feb 2019 12:40:01 +0000 (12:40 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Feb 2019 20:55:31 +0000 (12:55 -0800)
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 <maximmi@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/packet/af_packet.c

index 6afd6369d19ee8b80d807782815828b5cf803002..cac4c1a3f807d48adb19162d068a40f8592e252a 100644 (file)
@@ -1850,6 +1850,15 @@ oom:
        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_probe_transport_header(skb);
+}
 
 /*
  *     Output a raw packet to a device layer. This bypasses all the other
@@ -1970,7 +1979,7 @@ retry:
        if (unlikely(extra_len == 4))
                skb->no_fcs = 1;
 
-       skb_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_probe_transport_header(skb);
+       packet_parse_headers(skb, sock);
 
        return tp_len;
 }
@@ -2925,7 +2934,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                virtio_net_hdr_set_proto(skb, &vnet_hdr);
        }
 
-       skb_probe_transport_header(skb);
+       packet_parse_headers(skb, sock);
 
        if (unlikely(extra_len == 4))
                skb->no_fcs = 1;