summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/dst.h3
-rw-r--r--net/core/dst.c13
-rw-r--r--net/ipv4/route.c8
-rw-r--r--net/ipv6/route.c8
-rw-r--r--net/xfrm/xfrm_policy.c5
5 files changed, 21 insertions, 16 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index d214a5781c17..b7e47a7ad105 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -89,7 +89,8 @@ struct dst_ops
int (*gc)(void);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
void (*destroy)(struct dst_entry *);
- void (*ifdown)(struct dst_entry *, int how);
+ void (*ifdown)(struct dst_entry *,
+ struct net_device *dev, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
diff --git a/net/core/dst.c b/net/core/dst.c
index 001f8d484196..3bf6cc434814 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -220,12 +220,14 @@ again:
*
* Commented and originally written by Alexey.
*/
-static inline void dst_ifdown(struct dst_entry *dst, int unregister)
+static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ int unregister)
{
- struct net_device *dev = dst->dev;
-
if (dst->ops->ifdown)
- dst->ops->ifdown(dst, unregister);
+ dst->ops->ifdown(dst, dev, unregister);
+
+ if (dev != dst->dev)
+ return;
if (!unregister) {
dst->input = dst_discard_in;
@@ -252,8 +254,7 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
case NETDEV_DOWN:
spin_lock_bh(&dst_lock);
for (dst = dst_garbage_list; dst; dst = dst->next) {
- if (dst->dev == dev)
- dst_ifdown(dst, event != NETDEV_DOWN);
+ dst_ifdown(dst, dev, event != NETDEV_DOWN);
}
spin_unlock_bh(&dst_lock);
break;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8a06923f8451..24e7f12f1972 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -138,7 +138,8 @@ static struct timer_list rt_secret_timer;
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
static void ipv4_dst_destroy(struct dst_entry *dst);
-static void ipv4_dst_ifdown(struct dst_entry *dst, int how);
+static void ipv4_dst_ifdown(struct dst_entry *dst,
+ struct net_device *dev, int how);
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
@@ -1342,11 +1343,12 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
}
}
-static void ipv4_dst_ifdown(struct dst_entry *dst, int how)
+static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ int how)
{
struct rtable *rt = (struct rtable *) dst;
struct in_device *idev = rt->idev;
- if (idev && idev->dev != &loopback_dev) {
+ if (dev != &loopback_dev && idev && idev->dev == dev) {
struct in_device *loopback_idev = in_dev_get(&loopback_dev);
if (loopback_idev) {
rt->idev = loopback_idev;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 06ba75fcfff4..dd1703a09aa9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -84,7 +84,8 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static struct dst_entry *ip6_negative_advice(struct dst_entry *);
static void ip6_dst_destroy(struct dst_entry *);
-static void ip6_dst_ifdown(struct dst_entry *, int how);
+static void ip6_dst_ifdown(struct dst_entry *,
+ struct net_device *dev, int how);
static int ip6_dst_gc(void);
static int ip6_pkt_discard(struct sk_buff *skb);
@@ -153,12 +154,13 @@ static void ip6_dst_destroy(struct dst_entry *dst)
}
}
-static void ip6_dst_ifdown(struct dst_entry *dst, int how)
+static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ int how)
{
struct rt6_info *rt = (struct rt6_info *)dst;
struct inet6_dev *idev = rt->rt6i_idev;
- if (idev != NULL && idev->dev != &loopback_dev) {
+ if (dev != &loopback_dev && idev != NULL && idev->dev == dev) {
struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
if (loopback_idev != NULL) {
rt->rt6i_idev = loopback_idev;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 46104bdd70d2..450b0a6f55dd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1043,10 +1043,9 @@ static void xfrm_dst_destroy(struct dst_entry *dst)
dst->xfrm = NULL;
}
-static void xfrm_dst_ifdown(struct dst_entry *dst, int unregister)
+static void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ int unregister)
{
- struct net_device *dev = dst->dev;
-
if (!unregister)
return;