]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: ip_tunnel: add header_ops for layer 3 devices
authorJason A. Donenfeld <Jason@zx2c4.com>
Tue, 30 Jun 2020 01:06:18 +0000 (19:06 -0600)
committerDavid S. Miller <davem@davemloft.net>
Tue, 30 Jun 2020 19:29:39 +0000 (12:29 -0700)
Some devices that take straight up layer 3 packets benefit from having a
shared header_ops so that AF_PACKET sockets can inject packets that are
recognized. This shared infrastructure will be used by other drivers
that currently can't inject packets using AF_PACKET. It also exposes the
parser function, as it is useful in standalone form too.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip_tunnels.h
net/ipv4/ip_tunnel_core.c

index 076e5d7db7d3c45663d094aeef1010eeca461635..36025dea7612ac462a2582883a6ea1024c141081 100644 (file)
@@ -290,6 +290,9 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
                      struct ip_tunnel_parm *p, __u32 fwmark);
 void ip_tunnel_setup(struct net_device *dev, unsigned int net_id);
 
+extern const struct header_ops ip_tunnel_header_ops;
+__be16 ip_tunnel_parse_protocol(const struct sk_buff *skb);
+
 struct ip_tunnel_encap_ops {
        size_t (*encap_hlen)(struct ip_tunnel_encap *e);
        int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e,
index 181b7a2a024766a7370dbb657acac85ed1f49016..f8b419e2475c9f7ec55a2fb0e4c0906c1f5f7102 100644 (file)
@@ -844,3 +844,21 @@ void ip_tunnel_unneed_metadata(void)
        static_branch_dec(&ip_tunnel_metadata_cnt);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_unneed_metadata);
+
+/* Returns either the correct skb->protocol value, or 0 if invalid. */
+__be16 ip_tunnel_parse_protocol(const struct sk_buff *skb)
+{
+       if (skb_network_header(skb) >= skb->head &&
+           (skb_network_header(skb) + sizeof(struct iphdr)) <= skb_tail_pointer(skb) &&
+           ip_hdr(skb)->version == 4)
+               return htons(ETH_P_IP);
+       if (skb_network_header(skb) >= skb->head &&
+           (skb_network_header(skb) + sizeof(struct ipv6hdr)) <= skb_tail_pointer(skb) &&
+           ipv6_hdr(skb)->version == 6)
+               return htons(ETH_P_IPV6);
+       return 0;
+}
+EXPORT_SYMBOL(ip_tunnel_parse_protocol);
+
+const struct header_ops ip_tunnel_header_ops = { .parse_protocol = ip_tunnel_parse_protocol };
+EXPORT_SYMBOL(ip_tunnel_header_ops);