| From foo@baz Wed May 28 21:03:54 PDT 2014 |
| From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> |
| Date: Fri, 16 May 2014 08:34:39 +0300 |
| Subject: ipv4: ip_tunnels: disable cache for nbma gre tunnels |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> |
| |
| [ Upstream commit 22fb22eaebf4d16987f3fd9c3484c436ee0badf2 ] |
| |
| The connected check fails to check for ip_gre nbma mode tunnels |
| properly. ip_gre creates temporary tnl_params with daddr specified |
| to pass-in the actual target on per-packet basis from neighbor |
| layer. Detect these tunnels by inspecting the actual tunnel |
| configuration. |
| |
| Minimal test case: |
| ip route add 192.168.1.1/32 via 10.0.0.1 |
| ip route add 192.168.1.2/32 via 10.0.0.2 |
| ip tunnel add nbma0 mode gre key 1 tos c0 |
| ip addr add 172.17.0.0/16 dev nbma0 |
| ip link set nbma0 up |
| ip neigh add 172.17.0.1 lladdr 192.168.1.1 dev nbma0 |
| ip neigh add 172.17.0.2 lladdr 192.168.1.2 dev nbma0 |
| ping 172.17.0.1 |
| ping 172.17.0.2 |
| |
| The second ping should be going to 192.168.1.2 and head 10.0.0.2; |
| but cached gre tunnel level route is used and it's actually going |
| to 192.168.1.1 via 10.0.0.1. |
| |
| The lladdr's need to go to separate dst for the bug to trigger. |
| Test case uses separate route entries, but this can also happen |
| when the route entry is same: if there is a nexthop exception or |
| the GRE tunnel is IPsec'ed in which case the dst points to xfrm |
| bundle unique to the gre lladdr. |
| |
| Fixes: 7d442fab0a67 ("ipv4: Cache dst in tunnels") |
| Signed-off-by: Timo Teräs <timo.teras@iki.fi> |
| Cc: Tom Herbert <therbert@google.com> |
| Cc: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv4/ip_tunnel.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/net/ipv4/ip_tunnel.c |
| +++ b/net/ipv4/ip_tunnel.c |
| @@ -536,9 +536,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, |
| unsigned int max_headroom; /* The extra header space needed */ |
| __be32 dst; |
| int err; |
| - bool connected = true; |
| + bool connected; |
| |
| inner_iph = (const struct iphdr *)skb_inner_network_header(skb); |
| + connected = (tunnel->parms.iph.daddr != 0); |
| |
| dst = tnl_params->daddr; |
| if (dst == 0) { |