Export an encap_err_lookup() operation to match an ICMP error against a
valid VNI.

Reviewed-by: Sabrina Dubroca <s...@queasysnail.net>
Signed-off-by: Stefano Brivio <sbri...@redhat.com>
---
 drivers/net/vxlan.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 297cdeaef479..7706e392b2a7 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1552,6 +1552,34 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff 
*skb)
        return 0;
 }
 
+/* Callback from net/ipv{4,6}/udp.c to check that we have a VNI for errors */
+static int vxlan_err_lookup(struct sock *sk, struct sk_buff *skb)
+{
+       struct vxlan_dev *vxlan;
+       struct vxlan_sock *vs;
+       struct vxlanhdr *hdr;
+       __be32 vni;
+
+       if (skb->len < VXLAN_HLEN)
+               return -EINVAL;
+
+       hdr = vxlan_hdr(skb);
+
+       if (!(hdr->vx_flags & VXLAN_HF_VNI))
+               return -EINVAL;
+
+       vs = rcu_dereference_sk_user_data(sk);
+       if (!vs)
+               return -ENOENT;
+
+       vni = vxlan_vni(hdr->vx_vni);
+       vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni);
+       if (!vxlan)
+               return -ENOENT;
+
+       return 0;
+}
+
 static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
@@ -2948,6 +2976,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net 
*net, bool ipv6,
        tunnel_cfg.sk_user_data = vs;
        tunnel_cfg.encap_type = 1;
        tunnel_cfg.encap_rcv = vxlan_rcv;
+       tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
        tunnel_cfg.encap_destroy = NULL;
        tunnel_cfg.gro_receive = vxlan_gro_receive;
        tunnel_cfg.gro_complete = vxlan_gro_complete;
-- 
2.19.1

Reply via email to