aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-09-27 01:10:56 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:49 -0400
commit2774c7aba6c97a2535be3309a2209770953780b3 (patch)
tree9327c795707f6d723c6395c31e1c060e70b5e0db
parent0cc217e16cb8ca8ef2544363571fce94259900e0 (diff)
[NET]: Make the loopback device per network namespace.
This patch makes loopback_dev per network namespace. Adding code to create a different loopback device for each network namespace and adding the code to free a loopback device when a network namespace exits. This patch modifies all users the loopback_dev so they access it as init_net.loopback_dev, keeping all of the code compiling and working. A later pass will be needed to update the users to use something other than the initial network namespace. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/loopback.c26
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/net/net_namespace.h3
-rw-r--r--net/core/dst.c5
-rw-r--r--net/decnet/dn_dev.c4
-rw-r--r--net/decnet/dn_route.c14
-rw-r--r--net/ipv4/route.c18
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv6/addrconf.c18
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c2
-rw-r--r--net/ipv6/route.c12
-rw-r--r--net/ipv6/xfrm6_policy.c2
-rw-r--r--net/xfrm/xfrm_policy.c2
13 files changed, 64 insertions, 45 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index f3018bb7570d..0f9d8c60c964 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -57,6 +57,7 @@
57#include <linux/ip.h> 57#include <linux/ip.h>
58#include <linux/tcp.h> 58#include <linux/tcp.h>
59#include <linux/percpu.h> 59#include <linux/percpu.h>
60#include <net/net_namespace.h>
60 61
61struct pcpu_lstats { 62struct pcpu_lstats {
62 unsigned long packets; 63 unsigned long packets;
@@ -252,7 +253,7 @@ static void loopback_setup(struct net_device *dev)
252} 253}
253 254
254/* Setup and register the loopback device. */ 255/* Setup and register the loopback device. */
255static int __init loopback_init(void) 256static int loopback_net_init(struct net *net)
256{ 257{
257 struct net_device *dev; 258 struct net_device *dev;
258 int err; 259 int err;
@@ -262,12 +263,13 @@ static int __init loopback_init(void)
262 if (!dev) 263 if (!dev)
263 goto out; 264 goto out;
264 265
266 dev->nd_net = net;
265 err = register_netdev(dev); 267 err = register_netdev(dev);
266 if (err) 268 if (err)
267 goto out_free_netdev; 269 goto out_free_netdev;
268 270
269 err = 0; 271 err = 0;
270 loopback_dev = dev; 272 net->loopback_dev = dev;
271 273
272out: 274out:
273 if (err) 275 if (err)
@@ -279,7 +281,21 @@ out_free_netdev:
279 goto out; 281 goto out;
280} 282}
281 283
282fs_initcall(loopback_init); 284static void loopback_net_exit(struct net *net)
285{
286 struct net_device *dev = net->loopback_dev;
287
288 unregister_netdev(dev);
289}
290
291static struct pernet_operations loopback_net_ops = {
292 .init = loopback_net_init,
293 .exit = loopback_net_exit,
294};
295
296static int __init loopback_init(void)
297{
298 return register_pernet_device(&loopback_net_ops);
299}
283 300
284struct net_device *loopback_dev; 301fs_initcall(loopback_init);
285EXPORT_SYMBOL(loopback_dev);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2088097663b5..71cf409ad17e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -742,7 +742,6 @@ struct packet_type {
742#include <linux/interrupt.h> 742#include <linux/interrupt.h>
743#include <linux/notifier.h> 743#include <linux/notifier.h>
744 744
745extern struct net_device *loopback_dev; /* The loopback */
746extern rwlock_t dev_base_lock; /* Device list lock */ 745extern rwlock_t dev_base_lock; /* Device list lock */
747 746
748 747
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 3ea4194613ed..13b0e3b547f0 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -9,6 +9,7 @@
9#include <linux/list.h> 9#include <linux/list.h>
10 10
11struct proc_dir_entry; 11struct proc_dir_entry;
12struct net_device;
12struct net { 13struct net {
13 atomic_t count; /* To decided when the network 14 atomic_t count; /* To decided when the network
14 * namespace should be freed. 15 * namespace should be freed.
@@ -23,6 +24,8 @@ struct net {
23 struct proc_dir_entry *proc_net_stat; 24 struct proc_dir_entry *proc_net_stat;
24 struct proc_dir_entry *proc_net_root; 25 struct proc_dir_entry *proc_net_root;
25 26
27 struct net_device *loopback_dev; /* The loopback */
28
26 struct list_head dev_base_head; 29 struct list_head dev_base_head;
27 struct hlist_head *dev_name_head; 30 struct hlist_head *dev_name_head;
28 struct hlist_head *dev_index_head; 31 struct hlist_head *dev_index_head;
diff --git a/net/core/dst.c b/net/core/dst.c
index ad5ffa19d809..16958e64e577 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -18,6 +18,7 @@
18#include <linux/types.h> 18#include <linux/types.h>
19#include <net/net_namespace.h> 19#include <net/net_namespace.h>
20 20
21#include <net/net_namespace.h>
21#include <net/dst.h> 22#include <net/dst.h>
22 23
23/* 24/*
@@ -278,11 +279,11 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
278 if (!unregister) { 279 if (!unregister) {
279 dst->input = dst->output = dst_discard; 280 dst->input = dst->output = dst_discard;
280 } else { 281 } else {
281 dst->dev = loopback_dev; 282 dst->dev = init_net.loopback_dev;
282 dev_hold(dst->dev); 283 dev_hold(dst->dev);
283 dev_put(dev); 284 dev_put(dev);
284 if (dst->neighbour && dst->neighbour->dev == dev) { 285 if (dst->neighbour && dst->neighbour->dev == dev) {
285 dst->neighbour->dev = loopback_dev; 286 dst->neighbour->dev = init_net.loopback_dev;
286 dev_put(dev); 287 dev_put(dev);
287 dev_hold(dst->neighbour->dev); 288 dev_hold(dst->neighbour->dev);
288 } 289 }
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index bcaf4c5aa68e..26130afd8029 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -869,10 +869,10 @@ last_chance:
869 rv = dn_dev_get_first(dev, addr); 869 rv = dn_dev_get_first(dev, addr);
870 read_unlock(&dev_base_lock); 870 read_unlock(&dev_base_lock);
871 dev_put(dev); 871 dev_put(dev);
872 if (rv == 0 || dev == loopback_dev) 872 if (rv == 0 || dev == init_net.loopback_dev)
873 return rv; 873 return rv;
874 } 874 }
875 dev = loopback_dev; 875 dev = init_net.loopback_dev;
876 dev_hold(dev); 876 dev_hold(dev);
877 goto last_chance; 877 goto last_chance;
878} 878}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 96fe0aa1638e..b7ebf9947ebd 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -887,7 +887,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
887 .scope = RT_SCOPE_UNIVERSE, 887 .scope = RT_SCOPE_UNIVERSE,
888 } }, 888 } },
889 .mark = oldflp->mark, 889 .mark = oldflp->mark,
890 .iif = loopback_dev->ifindex, 890 .iif = init_net.loopback_dev->ifindex,
891 .oif = oldflp->oif }; 891 .oif = oldflp->oif };
892 struct dn_route *rt = NULL; 892 struct dn_route *rt = NULL;
893 struct net_device *dev_out = NULL, *dev; 893 struct net_device *dev_out = NULL, *dev;
@@ -904,7 +904,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
904 "dn_route_output_slow: dst=%04x src=%04x mark=%d" 904 "dn_route_output_slow: dst=%04x src=%04x mark=%d"
905 " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst), 905 " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
906 dn_ntohs(oldflp->fld_src), 906 dn_ntohs(oldflp->fld_src),
907 oldflp->mark, loopback_dev->ifindex, oldflp->oif); 907 oldflp->mark, init_net.loopback_dev->ifindex, oldflp->oif);
908 908
909 /* If we have an output interface, verify its a DECnet device */ 909 /* If we have an output interface, verify its a DECnet device */
910 if (oldflp->oif) { 910 if (oldflp->oif) {
@@ -957,7 +957,7 @@ source_ok:
957 err = -EADDRNOTAVAIL; 957 err = -EADDRNOTAVAIL;
958 if (dev_out) 958 if (dev_out)
959 dev_put(dev_out); 959 dev_put(dev_out);
960 dev_out = loopback_dev; 960 dev_out = init_net.loopback_dev;
961 dev_hold(dev_out); 961 dev_hold(dev_out);
962 if (!fl.fld_dst) { 962 if (!fl.fld_dst) {
963 fl.fld_dst = 963 fl.fld_dst =
@@ -966,7 +966,7 @@ source_ok:
966 if (!fl.fld_dst) 966 if (!fl.fld_dst)
967 goto out; 967 goto out;
968 } 968 }
969 fl.oif = loopback_dev->ifindex; 969 fl.oif = init_net.loopback_dev->ifindex;
970 res.type = RTN_LOCAL; 970 res.type = RTN_LOCAL;
971 goto make_route; 971 goto make_route;
972 } 972 }
@@ -1012,7 +1012,7 @@ source_ok:
1012 if (dev_out) 1012 if (dev_out)
1013 dev_put(dev_out); 1013 dev_put(dev_out);
1014 if (dn_dev_islocal(neigh->dev, fl.fld_dst)) { 1014 if (dn_dev_islocal(neigh->dev, fl.fld_dst)) {
1015 dev_out = loopback_dev; 1015 dev_out = init_net.loopback_dev;
1016 res.type = RTN_LOCAL; 1016 res.type = RTN_LOCAL;
1017 } else { 1017 } else {
1018 dev_out = neigh->dev; 1018 dev_out = neigh->dev;
@@ -1033,7 +1033,7 @@ source_ok:
1033 /* Possible improvement - check all devices for local addr */ 1033 /* Possible improvement - check all devices for local addr */
1034 if (dn_dev_islocal(dev_out, fl.fld_dst)) { 1034 if (dn_dev_islocal(dev_out, fl.fld_dst)) {
1035 dev_put(dev_out); 1035 dev_put(dev_out);
1036 dev_out = loopback_dev; 1036 dev_out = init_net.loopback_dev;
1037 dev_hold(dev_out); 1037 dev_hold(dev_out);
1038 res.type = RTN_LOCAL; 1038 res.type = RTN_LOCAL;
1039 goto select_source; 1039 goto select_source;
@@ -1069,7 +1069,7 @@ select_source:
1069 fl.fld_src = fl.fld_dst; 1069 fl.fld_src = fl.fld_dst;
1070 if (dev_out) 1070 if (dev_out)
1071 dev_put(dev_out); 1071 dev_put(dev_out);
1072 dev_out = loopback_dev; 1072 dev_out = init_net.loopback_dev;
1073 dev_hold(dev_out); 1073 dev_hold(dev_out);
1074 fl.oif = dev_out->ifindex; 1074 fl.oif = dev_out->ifindex;
1075 if (res.fi) 1075 if (res.fi)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index ca2878dc6188..2a9b363e820c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1402,8 +1402,8 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
1402{ 1402{
1403 struct rtable *rt = (struct rtable *) dst; 1403 struct rtable *rt = (struct rtable *) dst;
1404 struct in_device *idev = rt->idev; 1404 struct in_device *idev = rt->idev;
1405 if (dev != loopback_dev && idev && idev->dev == dev) { 1405 if (dev != init_net.loopback_dev && idev && idev->dev == dev) {
1406 struct in_device *loopback_idev = in_dev_get(loopback_dev); 1406 struct in_device *loopback_idev = in_dev_get(init_net.loopback_dev);
1407 if (loopback_idev) { 1407 if (loopback_idev) {
1408 rt->idev = loopback_idev; 1408 rt->idev = loopback_idev;
1409 in_dev_put(idev); 1409 in_dev_put(idev);
@@ -1555,7 +1555,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1555#endif 1555#endif
1556 rth->rt_iif = 1556 rth->rt_iif =
1557 rth->fl.iif = dev->ifindex; 1557 rth->fl.iif = dev->ifindex;
1558 rth->u.dst.dev = loopback_dev; 1558 rth->u.dst.dev = init_net.loopback_dev;
1559 dev_hold(rth->u.dst.dev); 1559 dev_hold(rth->u.dst.dev);
1560 rth->idev = in_dev_get(rth->u.dst.dev); 1560 rth->idev = in_dev_get(rth->u.dst.dev);
1561 rth->fl.oif = 0; 1561 rth->fl.oif = 0;
@@ -1812,7 +1812,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1812 if (res.type == RTN_LOCAL) { 1812 if (res.type == RTN_LOCAL) {
1813 int result; 1813 int result;
1814 result = fib_validate_source(saddr, daddr, tos, 1814 result = fib_validate_source(saddr, daddr, tos,
1815 loopback_dev->ifindex, 1815 init_net.loopback_dev->ifindex,
1816 dev, &spec_dst, &itag); 1816 dev, &spec_dst, &itag);
1817 if (result < 0) 1817 if (result < 0)
1818 goto martian_source; 1818 goto martian_source;
@@ -1879,7 +1879,7 @@ local_input:
1879#endif 1879#endif
1880 rth->rt_iif = 1880 rth->rt_iif =
1881 rth->fl.iif = dev->ifindex; 1881 rth->fl.iif = dev->ifindex;
1882 rth->u.dst.dev = loopback_dev; 1882 rth->u.dst.dev = init_net.loopback_dev;
1883 dev_hold(rth->u.dst.dev); 1883 dev_hold(rth->u.dst.dev);
1884 rth->idev = in_dev_get(rth->u.dst.dev); 1884 rth->idev = in_dev_get(rth->u.dst.dev);
1885 rth->rt_gateway = daddr; 1885 rth->rt_gateway = daddr;
@@ -2149,7 +2149,7 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
2149 RT_SCOPE_UNIVERSE), 2149 RT_SCOPE_UNIVERSE),
2150 } }, 2150 } },
2151 .mark = oldflp->mark, 2151 .mark = oldflp->mark,
2152 .iif = loopback_dev->ifindex, 2152 .iif = init_net.loopback_dev->ifindex,
2153 .oif = oldflp->oif }; 2153 .oif = oldflp->oif };
2154 struct fib_result res; 2154 struct fib_result res;
2155 unsigned flags = 0; 2155 unsigned flags = 0;
@@ -2243,9 +2243,9 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
2243 fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK); 2243 fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK);
2244 if (dev_out) 2244 if (dev_out)
2245 dev_put(dev_out); 2245 dev_put(dev_out);
2246 dev_out = loopback_dev; 2246 dev_out = init_net.loopback_dev;
2247 dev_hold(dev_out); 2247 dev_hold(dev_out);
2248 fl.oif = loopback_dev->ifindex; 2248 fl.oif = init_net.loopback_dev->ifindex;
2249 res.type = RTN_LOCAL; 2249 res.type = RTN_LOCAL;
2250 flags |= RTCF_LOCAL; 2250 flags |= RTCF_LOCAL;
2251 goto make_route; 2251 goto make_route;
@@ -2290,7 +2290,7 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
2290 fl.fl4_src = fl.fl4_dst; 2290 fl.fl4_src = fl.fl4_dst;
2291 if (dev_out) 2291 if (dev_out)
2292 dev_put(dev_out); 2292 dev_put(dev_out);
2293 dev_out = loopback_dev; 2293 dev_out = init_net.loopback_dev;
2294 dev_hold(dev_out); 2294 dev_hold(dev_out);
2295 fl.oif = dev_out->ifindex; 2295 fl.oif = dev_out->ifindex;
2296 if (res.fi) 2296 if (res.fi)
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 29ab3de8c47f..329825ca68fe 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -306,7 +306,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
306 306
307 xdst = (struct xfrm_dst *)dst; 307 xdst = (struct xfrm_dst *)dst;
308 if (xdst->u.rt.idev->dev == dev) { 308 if (xdst->u.rt.idev->dev == dev) {
309 struct in_device *loopback_idev = in_dev_get(loopback_dev); 309 struct in_device *loopback_idev = in_dev_get(init_net.loopback_dev);
310 BUG_ON(!loopback_idev); 310 BUG_ON(!loopback_idev);
311 311
312 do { 312 do {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b43574f73375..6d5c3c299148 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2410,7 +2410,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2410 2410
2411 ASSERT_RTNL(); 2411 ASSERT_RTNL();
2412 2412
2413 if (dev == loopback_dev && how == 1) 2413 if (dev == init_net.loopback_dev && how == 1)
2414 how = 0; 2414 how = 0;
2415 2415
2416 rt6_ifdown(dev); 2416 rt6_ifdown(dev);
@@ -4212,19 +4212,19 @@ int __init addrconf_init(void)
4212 * device and it being up should be removed. 4212 * device and it being up should be removed.
4213 */ 4213 */
4214 rtnl_lock(); 4214 rtnl_lock();
4215 if (!ipv6_add_dev(loopback_dev)) 4215 if (!ipv6_add_dev(init_net.loopback_dev))
4216 err = -ENOMEM; 4216 err = -ENOMEM;
4217 rtnl_unlock(); 4217 rtnl_unlock();
4218 if (err) 4218 if (err)
4219 return err; 4219 return err;
4220 4220
4221 ip6_null_entry.u.dst.dev = loopback_dev; 4221 ip6_null_entry.u.dst.dev = init_net.loopback_dev;
4222 ip6_null_entry.rt6i_idev = in6_dev_get(loopback_dev); 4222 ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
4223#ifdef CONFIG_IPV6_MULTIPLE_TABLES 4223#ifdef CONFIG_IPV6_MULTIPLE_TABLES
4224 ip6_prohibit_entry.u.dst.dev = loopback_dev; 4224 ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev;
4225 ip6_prohibit_entry.rt6i_idev = in6_dev_get(loopback_dev); 4225 ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
4226 ip6_blk_hole_entry.u.dst.dev = loopback_dev; 4226 ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev;
4227 ip6_blk_hole_entry.rt6i_idev = in6_dev_get(loopback_dev); 4227 ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
4228#endif 4228#endif
4229 4229
4230 register_netdevice_notifier(&ipv6_dev_notf); 4230 register_netdevice_notifier(&ipv6_dev_notf);
@@ -4279,7 +4279,7 @@ void __exit addrconf_cleanup(void)
4279 continue; 4279 continue;
4280 addrconf_ifdown(dev, 1); 4280 addrconf_ifdown(dev, 1);
4281 } 4281 }
4282 addrconf_ifdown(loopback_dev, 2); 4282 addrconf_ifdown(init_net.loopback_dev, 2);
4283 4283
4284 /* 4284 /*
4285 * Check hash table. 4285 * Check hash table.
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 50860531cd3c..3fd08d5567a6 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -167,7 +167,7 @@ static inline void
167send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum) 167send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum)
168{ 168{
169 if (hooknum == NF_IP6_LOCAL_OUT && skb_in->dev == NULL) 169 if (hooknum == NF_IP6_LOCAL_OUT && skb_in->dev == NULL)
170 skb_in->dev = loopback_dev; 170 skb_in->dev = init_net.loopback_dev;
171 171
172 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); 172 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL);
173} 173}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a7a21a7ba790..6ff19f9eb9ee 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -221,8 +221,8 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
221 struct rt6_info *rt = (struct rt6_info *)dst; 221 struct rt6_info *rt = (struct rt6_info *)dst;
222 struct inet6_dev *idev = rt->rt6i_idev; 222 struct inet6_dev *idev = rt->rt6i_idev;
223 223
224 if (dev != loopback_dev && idev != NULL && idev->dev == dev) { 224 if (dev != init_net.loopback_dev && idev != NULL && idev->dev == dev) {
225 struct inet6_dev *loopback_idev = in6_dev_get(loopback_dev); 225 struct inet6_dev *loopback_idev = in6_dev_get(init_net.loopback_dev);
226 if (loopback_idev != NULL) { 226 if (loopback_idev != NULL) {
227 rt->rt6i_idev = loopback_idev; 227 rt->rt6i_idev = loopback_idev;
228 in6_dev_put(idev); 228 in6_dev_put(idev);
@@ -1185,12 +1185,12 @@ int ip6_route_add(struct fib6_config *cfg)
1185 if ((cfg->fc_flags & RTF_REJECT) || 1185 if ((cfg->fc_flags & RTF_REJECT) ||
1186 (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { 1186 (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
1187 /* hold loopback dev/idev if we haven't done so. */ 1187 /* hold loopback dev/idev if we haven't done so. */
1188 if (dev != loopback_dev) { 1188 if (dev != init_net.loopback_dev) {
1189 if (dev) { 1189 if (dev) {
1190 dev_put(dev); 1190 dev_put(dev);
1191 in6_dev_put(idev); 1191 in6_dev_put(idev);
1192 } 1192 }
1193 dev = loopback_dev; 1193 dev = init_net.loopback_dev;
1194 dev_hold(dev); 1194 dev_hold(dev);
1195 idev = in6_dev_get(dev); 1195 idev = in6_dev_get(dev);
1196 if (!idev) { 1196 if (!idev) {
@@ -1894,13 +1894,13 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1894 if (rt == NULL) 1894 if (rt == NULL)
1895 return ERR_PTR(-ENOMEM); 1895 return ERR_PTR(-ENOMEM);
1896 1896
1897 dev_hold(loopback_dev); 1897 dev_hold(init_net.loopback_dev);
1898 in6_dev_hold(idev); 1898 in6_dev_hold(idev);
1899 1899
1900 rt->u.dst.flags = DST_HOST; 1900 rt->u.dst.flags = DST_HOST;
1901 rt->u.dst.input = ip6_input; 1901 rt->u.dst.input = ip6_input;
1902 rt->u.dst.output = ip6_output; 1902 rt->u.dst.output = ip6_output;
1903 rt->rt6i_dev = loopback_dev; 1903 rt->rt6i_dev = init_net.loopback_dev;
1904 rt->rt6i_idev = idev; 1904 rt->rt6i_idev = idev;
1905 rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); 1905 rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
1906 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); 1906 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index cc07216cfd59..15aa4c58c315 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -375,7 +375,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
375 375
376 xdst = (struct xfrm_dst *)dst; 376 xdst = (struct xfrm_dst *)dst;
377 if (xdst->u.rt6.rt6i_idev->dev == dev) { 377 if (xdst->u.rt6.rt6i_idev->dev == dev) {
378 struct inet6_dev *loopback_idev = in6_dev_get(loopback_dev); 378 struct inet6_dev *loopback_idev = in6_dev_get(init_net.loopback_dev);
379 BUG_ON(!loopback_idev); 379 BUG_ON(!loopback_idev);
380 380
381 do { 381 do {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d6dfd7d1948f..76f172f13f90 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1949,7 +1949,7 @@ static int stale_bundle(struct dst_entry *dst)
1949void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) 1949void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
1950{ 1950{
1951 while ((dst = dst->child) && dst->xfrm && dst->dev == dev) { 1951 while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
1952 dst->dev = loopback_dev; 1952 dst->dev = init_net.loopback_dev;
1953 dev_hold(dst->dev); 1953 dev_hold(dst->dev);
1954 dev_put(dev); 1954 dev_put(dev);
1955 } 1955 }