diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_vti.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 16a7e81e3f99..ace10d0b3aac 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -95,6 +95,7 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote, | |||
95 | unsigned int hash = HASH(remote, local); | 95 | unsigned int hash = HASH(remote, local); |
96 | struct ip6_tnl *t; | 96 | struct ip6_tnl *t; |
97 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); | 97 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); |
98 | struct in6_addr any; | ||
98 | 99 | ||
99 | for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) { | 100 | for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) { |
100 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 101 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
@@ -102,6 +103,22 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote, | |||
102 | (t->dev->flags & IFF_UP)) | 103 | (t->dev->flags & IFF_UP)) |
103 | return t; | 104 | return t; |
104 | } | 105 | } |
106 | |||
107 | memset(&any, 0, sizeof(any)); | ||
108 | hash = HASH(&any, local); | ||
109 | for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) { | ||
110 | if (ipv6_addr_equal(local, &t->parms.laddr) && | ||
111 | (t->dev->flags & IFF_UP)) | ||
112 | return t; | ||
113 | } | ||
114 | |||
115 | hash = HASH(remote, &any); | ||
116 | for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) { | ||
117 | if (ipv6_addr_equal(remote, &t->parms.raddr) && | ||
118 | (t->dev->flags & IFF_UP)) | ||
119 | return t; | ||
120 | } | ||
121 | |||
105 | t = rcu_dereference(ip6n->tnls_wc[0]); | 122 | t = rcu_dereference(ip6n->tnls_wc[0]); |
106 | if (t && (t->dev->flags & IFF_UP)) | 123 | if (t && (t->dev->flags & IFF_UP)) |
107 | return t; | 124 | return t; |