]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/sit.c
sit: strictly restrict incoming traffic to tunnel link device
[net-next-2.6.git] / net / ipv6 / sit.c
index e62504133c77d6e3a60045045b35249cc976579c..dfedd56ee104369e074feecf992ced50c4925ed1 100644 (file)
@@ -80,7 +80,7 @@ struct sit_net {
 static DEFINE_RWLOCK(ipip6_lock);
 
 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 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) {
                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;
        }
        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;
        }
        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;
        }
-       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 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) {
                if (local == t->parms.iph.saddr &&
-                   remote == t->parms.iph.daddr) {
+                   remote == t->parms.iph.daddr &&
+                   parms->link == t->parms.link) {
                        if (create)
                                return NULL;
                        else
@@ -451,7 +459,10 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        err = -ENOENT;
 
        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)
                goto out;
 
@@ -486,8 +497,9 @@ static int ipip6_rcv(struct sk_buff *skb)
        iph = ip_hdr(skb);
 
        read_lock(&ipip6_lock);
-       if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev),
-                                       iph->saddr, iph->daddr)) != NULL) {
+       tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
+                                    iph->saddr, iph->daddr);
+       if (tunnel != NULL) {
                secpath_reset(skb);
                skb->mac_header = skb->network_header;
                skb_reset_network_header(skb);