diff options
author | Sascha Hlusiak <contact@saschahlusiak.de> | 2009-05-19 08:56:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-19 19:02:00 -0400 |
commit | 4fddbf5d7854b0a615c6481988895016f5d038d2 (patch) | |
tree | 7f8424937f50c198b3efef5459c7da78ee493695 /net/ipv6/sit.c | |
parent | 8db99e5717507729a9eb49108facb7e528340376 (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.c | 30 |
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 { | |||
80 | static DEFINE_RWLOCK(ipip6_lock); | 80 | static DEFINE_RWLOCK(ipip6_lock); |
81 | 81 | ||
82 | static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, | 82 | static 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); |