aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_tunnel.c
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2014-11-05 02:03:50 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-06 14:19:20 -0500
commitea3dc9601bda69d8d695b57c4f7a997cd7039781 (patch)
treecebdab7c6b281e52d54a96e30738539825448f92 /net/ipv6/ip6_tunnel.c
parentd50051407f136028108cfda068d55ef053a54fe1 (diff)
ip6_tunnel: Add support for wildcard tunnel endpoints.
This patch adds support for tunnels with local or remote wildcard endpoints. With this we get a NBMA tunnel mode like we have it for ipv4 and sit tunnels. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_tunnel.c')
-rw-r--r--net/ipv6/ip6_tunnel.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a8f94ff9c606..4550d08f44de 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -183,6 +183,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_
183 unsigned int hash = HASH(remote, local); 183 unsigned int hash = HASH(remote, local);
184 struct ip6_tnl *t; 184 struct ip6_tnl *t;
185 struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); 185 struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
186 struct in6_addr any;
186 187
187 for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { 188 for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
188 if (ipv6_addr_equal(local, &t->parms.laddr) && 189 if (ipv6_addr_equal(local, &t->parms.laddr) &&
@@ -190,6 +191,22 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_
190 (t->dev->flags & IFF_UP)) 191 (t->dev->flags & IFF_UP))
191 return t; 192 return t;
192 } 193 }
194
195 memset(&any, 0, sizeof(any));
196 hash = HASH(&any, local);
197 for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
198 if (ipv6_addr_equal(local, &t->parms.laddr) &&
199 (t->dev->flags & IFF_UP))
200 return t;
201 }
202
203 hash = HASH(remote, &any);
204 for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
205 if (ipv6_addr_equal(remote, &t->parms.raddr) &&
206 (t->dev->flags & IFF_UP))
207 return t;
208 }
209
193 t = rcu_dereference(ip6n->tnls_wc[0]); 210 t = rcu_dereference(ip6n->tnls_wc[0]);
194 if (t && (t->dev->flags & IFF_UP)) 211 if (t && (t->dev->flags & IFF_UP))
195 return t; 212 return t;
@@ -979,7 +996,29 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
979 u8 proto; 996 u8 proto;
980 int err = -1; 997 int err = -1;
981 998
982 if (!fl6->flowi6_mark) 999 /* NBMA tunnel */
1000 if (ipv6_addr_any(&t->parms.raddr)) {
1001 struct in6_addr *addr6;
1002 struct neighbour *neigh;
1003 int addr_type;
1004
1005 if (!skb_dst(skb))
1006 goto tx_err_link_failure;
1007
1008 neigh = dst_neigh_lookup(skb_dst(skb),
1009 &ipv6_hdr(skb)->daddr);
1010 if (!neigh)
1011 goto tx_err_link_failure;
1012
1013 addr6 = (struct in6_addr *)&neigh->primary_key;
1014 addr_type = ipv6_addr_type(addr6);
1015
1016 if (addr_type == IPV6_ADDR_ANY)
1017 addr6 = &ipv6_hdr(skb)->daddr;
1018
1019 memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
1020 neigh_release(neigh);
1021 } else if (!fl6->flowi6_mark)
983 dst = ip6_tnl_dst_check(t); 1022 dst = ip6_tnl_dst_check(t);
984 1023
985 if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr)) 1024 if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))