diff options
author | Lorenzo Bianconi <lorenzo.bianconi@redhat.com> | 2019-01-18 06:05:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-01-22 14:52:17 -0500 |
commit | cb73ee40b1b381eaf3749e6dbeed567bb38e5258 (patch) | |
tree | 4a46c80cac3f7bb0f044f1cbf2d73a66129a9456 | |
parent | 56cb4e5034998b5522a657957321ca64ca2ea0a0 (diff) |
net: ip_gre: use erspan key field for tunnel lookup
Use ERSPAN key header field as tunnel key in gre_parse_header routine
since ERSPAN protocol sets the key field of the external GRE header to
0 resulting in a tunnel lookup fail in ip6gre_err.
In addition remove key field parsing and pskb_may_pull check in
erspan_rcv and ip6erspan_rcv
Fixes: 5a963eb61b7c ("ip6_gre: Add ERSPAN native tunnel support")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/gre_demux.c | 17 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 9 | ||||
-rw-r--r-- | net/ipv6/ip6_gre.c | 4 |
3 files changed, 17 insertions, 13 deletions
diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index a4bf22ee3aed..7c4a41dc04bb 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <net/protocol.h> | 26 | #include <net/protocol.h> |
27 | #include <net/gre.h> | 27 | #include <net/gre.h> |
28 | #include <net/erspan.h> | ||
28 | 29 | ||
29 | #include <net/icmp.h> | 30 | #include <net/icmp.h> |
30 | #include <net/route.h> | 31 | #include <net/route.h> |
@@ -119,6 +120,22 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
119 | hdr_len += 4; | 120 | hdr_len += 4; |
120 | } | 121 | } |
121 | tpi->hdr_len = hdr_len; | 122 | tpi->hdr_len = hdr_len; |
123 | |||
124 | /* ERSPAN ver 1 and 2 protocol sets GRE key field | ||
125 | * to 0 and sets the configured key in the | ||
126 | * inner erspan header field | ||
127 | */ | ||
128 | if (greh->protocol == htons(ETH_P_ERSPAN) || | ||
129 | greh->protocol == htons(ETH_P_ERSPAN2)) { | ||
130 | struct erspan_base_hdr *ershdr; | ||
131 | |||
132 | if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr))) | ||
133 | return -EINVAL; | ||
134 | |||
135 | ershdr = (struct erspan_base_hdr *)options; | ||
136 | tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||
137 | } | ||
138 | |||
122 | return hdr_len; | 139 | return hdr_len; |
123 | } | 140 | } |
124 | EXPORT_SYMBOL(gre_parse_header); | 141 | EXPORT_SYMBOL(gre_parse_header); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index b1a74d80d868..20a64fe6254b 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -268,20 +268,11 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
268 | int len; | 268 | int len; |
269 | 269 | ||
270 | itn = net_generic(net, erspan_net_id); | 270 | itn = net_generic(net, erspan_net_id); |
271 | len = gre_hdr_len + sizeof(*ershdr); | ||
272 | |||
273 | /* Check based hdr len */ | ||
274 | if (unlikely(!pskb_may_pull(skb, len))) | ||
275 | return PACKET_REJECT; | ||
276 | 271 | ||
277 | iph = ip_hdr(skb); | 272 | iph = ip_hdr(skb); |
278 | ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); | 273 | ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); |
279 | ver = ershdr->ver; | 274 | ver = ershdr->ver; |
280 | 275 | ||
281 | /* The original GRE header does not have key field, | ||
282 | * Use ERSPAN 10-bit session ID as key. | ||
283 | */ | ||
284 | tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||
285 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, | 276 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, |
286 | tpi->flags | TUNNEL_KEY, | 277 | tpi->flags | TUNNEL_KEY, |
287 | iph->saddr, iph->daddr, tpi->key); | 278 | iph->saddr, iph->daddr, tpi->key); |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index b1be67ca6768..4416368dbd49 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -534,13 +534,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, | |||
534 | struct ip6_tnl *tunnel; | 534 | struct ip6_tnl *tunnel; |
535 | u8 ver; | 535 | u8 ver; |
536 | 536 | ||
537 | if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) | ||
538 | return PACKET_REJECT; | ||
539 | |||
540 | ipv6h = ipv6_hdr(skb); | 537 | ipv6h = ipv6_hdr(skb); |
541 | ershdr = (struct erspan_base_hdr *)skb->data; | 538 | ershdr = (struct erspan_base_hdr *)skb->data; |
542 | ver = ershdr->ver; | 539 | ver = ershdr->ver; |
543 | tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||
544 | 540 | ||
545 | tunnel = ip6gre_tunnel_lookup(skb->dev, | 541 | tunnel = ip6gre_tunnel_lookup(skb->dev, |
546 | &ipv6h->saddr, &ipv6h->daddr, tpi->key, | 542 | &ipv6h->saddr, &ipv6h->daddr, tpi->key, |