aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
authorSascha Hlusiak <contact@saschahlusiak.de>2009-05-19 08:56:49 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-19 19:02:00 -0400
commit4fddbf5d7854b0a615c6481988895016f5d038d2 (patch)
tree7f8424937f50c198b3efef5459c7da78ee493695 /net/ipv6/sit.c
parent8db99e5717507729a9eb49108facb7e528340376 (diff)
sit: strictly restrict incoming traffic to tunnel link device
Check link device when looking up a tunnel. When a tunnel is linked to a interface, traffic from a different interface must not reach the tunnel. This also allows creating of multiple tunnels with the same endpoints, if the link device differs. Signed-off-by: Sascha Hlusiak <contact@saschahlusiak.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r--net/ipv6/sit.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index e62504133c77..dfedd56ee104 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -80,7 +80,7 @@ struct sit_net {
80static DEFINE_RWLOCK(ipip6_lock); 80static DEFINE_RWLOCK(ipip6_lock);
81 81
82static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, 82static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
83 __be32 remote, __be32 local) 83 struct net_device *dev, __be32 remote, __be32 local)
84{ 84{
85 unsigned h0 = HASH(remote); 85 unsigned h0 = HASH(remote);
86 unsigned h1 = HASH(local); 86 unsigned h1 = HASH(local);
@@ -89,18 +89,25 @@ static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
89 89
90 for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) { 90 for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) {
91 if (local == t->parms.iph.saddr && 91 if (local == t->parms.iph.saddr &&
92 remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) 92 remote == t->parms.iph.daddr &&
93 (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
94 (t->dev->flags & IFF_UP))
93 return t; 95 return t;
94 } 96 }
95 for (t = sitn->tunnels_r[h0]; t; t = t->next) { 97 for (t = sitn->tunnels_r[h0]; t; t = t->next) {
96 if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) 98 if (remote == t->parms.iph.daddr &&
99 (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
100 (t->dev->flags & IFF_UP))
97 return t; 101 return t;
98 } 102 }
99 for (t = sitn->tunnels_l[h1]; t; t = t->next) { 103 for (t = sitn->tunnels_l[h1]; t; t = t->next) {
100 if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) 104 if (local == t->parms.iph.saddr &&
105 (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
106 (t->dev->flags & IFF_UP))
101 return t; 107 return t;
102 } 108 }
103 if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) 109 t = sitn->tunnels_wc[0];
110 if ((t != NULL) && (t->dev->flags & IFF_UP))
104 return t; 111 return t;
105 return NULL; 112 return NULL;
106} 113}
@@ -166,7 +173,8 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net,
166 173
167 for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { 174 for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) {
168 if (local == t->parms.iph.saddr && 175 if (local == t->parms.iph.saddr &&
169 remote == t->parms.iph.daddr) { 176 remote == t->parms.iph.daddr &&
177 parms->link == t->parms.link) {
170 if (create) 178 if (create)
171 return NULL; 179 return NULL;
172 else 180 else
@@ -451,7 +459,10 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
451 err = -ENOENT; 459 err = -ENOENT;
452 460
453 read_lock(&ipip6_lock); 461 read_lock(&ipip6_lock);
454 t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); 462 t = ipip6_tunnel_lookup(dev_net(skb->dev),
463 skb->dev,
464 iph->daddr,
465 iph->saddr);
455 if (t == NULL || t->parms.iph.daddr == 0) 466 if (t == NULL || t->parms.iph.daddr == 0)
456 goto out; 467 goto out;
457 468
@@ -486,8 +497,9 @@ static int ipip6_rcv(struct sk_buff *skb)
486 iph = ip_hdr(skb); 497 iph = ip_hdr(skb);
487 498
488 read_lock(&ipip6_lock); 499 read_lock(&ipip6_lock);
489 if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), 500 tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
490 iph->saddr, iph->daddr)) != NULL) { 501 iph->saddr, iph->daddr);
502 if (tunnel != NULL) {
491 secpath_reset(skb); 503 secpath_reset(skb);
492 skb->mac_header = skb->network_header; 504 skb->mac_header = skb->network_header;
493 skb_reset_network_header(skb); 505 skb_reset_network_header(skb);