mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
8db99e5717
commit
4fddbf5d78
|
@ -80,7 +80,7 @@ struct sit_net {
|
||||||
static DEFINE_RWLOCK(ipip6_lock);
|
static DEFINE_RWLOCK(ipip6_lock);
|
||||||
|
|
||||||
static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
|
static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
|
||||||
__be32 remote, __be32 local)
|
struct net_device *dev, __be32 remote, __be32 local)
|
||||||
{
|
{
|
||||||
unsigned h0 = HASH(remote);
|
unsigned h0 = HASH(remote);
|
||||||
unsigned h1 = HASH(local);
|
unsigned h1 = HASH(local);
|
||||||
|
@ -89,18 +89,25 @@ static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
|
||||||
|
|
||||||
for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) {
|
for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) {
|
||||||
if (local == t->parms.iph.saddr &&
|
if (local == t->parms.iph.saddr &&
|
||||||
remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
|
remote == t->parms.iph.daddr &&
|
||||||
|
(!dev || !t->parms.link || dev->iflink == t->parms.link) &&
|
||||||
|
(t->dev->flags & IFF_UP))
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
for (t = sitn->tunnels_r[h0]; t; t = t->next) {
|
for (t = sitn->tunnels_r[h0]; t; t = t->next) {
|
||||||
if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
|
if (remote == t->parms.iph.daddr &&
|
||||||
|
(!dev || !t->parms.link || dev->iflink == t->parms.link) &&
|
||||||
|
(t->dev->flags & IFF_UP))
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
for (t = sitn->tunnels_l[h1]; t; t = t->next) {
|
for (t = sitn->tunnels_l[h1]; t; t = t->next) {
|
||||||
if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
|
if (local == t->parms.iph.saddr &&
|
||||||
|
(!dev || !t->parms.link || dev->iflink == t->parms.link) &&
|
||||||
|
(t->dev->flags & IFF_UP))
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
|
t = sitn->tunnels_wc[0];
|
||||||
|
if ((t != NULL) && (t->dev->flags & IFF_UP))
|
||||||
return t;
|
return t;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +173,8 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net,
|
||||||
|
|
||||||
for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) {
|
for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) {
|
||||||
if (local == t->parms.iph.saddr &&
|
if (local == t->parms.iph.saddr &&
|
||||||
remote == t->parms.iph.daddr) {
|
remote == t->parms.iph.daddr &&
|
||||||
|
parms->link == t->parms.link) {
|
||||||
if (create)
|
if (create)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
|
@ -451,7 +459,10 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
|
||||||
err = -ENOENT;
|
err = -ENOENT;
|
||||||
|
|
||||||
read_lock(&ipip6_lock);
|
read_lock(&ipip6_lock);
|
||||||
t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
|
t = ipip6_tunnel_lookup(dev_net(skb->dev),
|
||||||
|
skb->dev,
|
||||||
|
iph->daddr,
|
||||||
|
iph->saddr);
|
||||||
if (t == NULL || t->parms.iph.daddr == 0)
|
if (t == NULL || t->parms.iph.daddr == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -486,8 +497,9 @@ static int ipip6_rcv(struct sk_buff *skb)
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
|
|
||||||
read_lock(&ipip6_lock);
|
read_lock(&ipip6_lock);
|
||||||
if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev),
|
tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
|
||||||
iph->saddr, iph->daddr)) != NULL) {
|
iph->saddr, iph->daddr);
|
||||||
|
if (tunnel != NULL) {
|
||||||
secpath_reset(skb);
|
secpath_reset(skb);
|
||||||
skb->mac_header = skb->network_header;
|
skb->mac_header = skb->network_header;
|
||||||
skb_reset_network_header(skb);
|
skb_reset_network_header(skb);
|
||||||
|
|
Loading…
Reference in New Issue