diff options
author | Daniel Lezcano <dlezcano@fr.ibm.com> | 2008-03-27 00:52:32 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-27 00:52:32 +0100 |
commit | 6ab57e7e7fa316552d0f94eaebf1def1d49f18da (patch) | |
tree | 5e0f5d2d9d302758a6c3bebd91ff0c11b110f5a1 /net | |
parent | [IPV6]: Fix potential net leak and oops in ipv6 routing code. (diff) | |
download | linux-6ab57e7e7fa316552d0f94eaebf1def1d49f18da.tar.xz linux-6ab57e7e7fa316552d0f94eaebf1def1d49f18da.zip |
[NETNS][IPV6] anycast - handle several network namespace
Make use of the network namespace information to have this protocol to
handle several network namespace.
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/af_inet6.c | 12 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 38 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 2 |
3 files changed, 29 insertions, 23 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 12f04e9d3e88..1731b0abf7f5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -862,11 +862,16 @@ static int inet6_net_init(struct net *net) err = tcp6_proc_init(net); if (err) goto proc_tcp6_fail; + err = ac6_proc_init(net); + if (err) + goto proc_ac6_fail; out: #endif return err; #ifdef CONFIG_PROC_FS +proc_ac6_fail: + tcp6_proc_exit(net); proc_tcp6_fail: udp6_proc_exit(net); goto out; @@ -878,6 +883,7 @@ static void inet6_net_exit(struct net *net) #ifdef CONFIG_PROC_FS udp6_proc_exit(net); tcp6_proc_exit(net); + ac6_proc_exit(net); #endif } @@ -965,9 +971,6 @@ static int __init inet6_init(void) goto proc_udplite6_fail; if (ipv6_misc_proc_init()) goto proc_misc6_fail; - - if (ac6_proc_init()) - goto proc_anycast6_fail; if (if6_proc_init()) goto proc_if6_fail; #endif @@ -1039,8 +1042,6 @@ ip6_route_fail: #ifdef CONFIG_PROC_FS if6_proc_exit(); proc_if6_fail: - ac6_proc_exit(); -proc_anycast6_fail: ipv6_misc_proc_exit(); proc_misc6_fail: udplite6_proc_exit(); @@ -1101,7 +1102,6 @@ static void __exit inet6_exit(void) /* Cleanup code parts. */ if6_proc_exit(); - ac6_proc_exit(); ipv6_misc_proc_exit(); udplite6_proc_exit(); raw6_proc_exit(); diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 96868b994b37..463bd95d6b13 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -82,6 +82,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) struct net_device *dev = NULL; struct inet6_dev *idev; struct ipv6_ac_socklist *pac; + struct net *net = sock_net(sk); int ishost = !ipv6_devconf.forwarding; int err = 0; @@ -89,7 +90,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) return -EPERM; if (ipv6_addr_is_multicast(addr)) return -EINVAL; - if (ipv6_chk_addr(&init_net, addr, NULL, 0)) + if (ipv6_chk_addr(net, addr, NULL, 0)) return -EINVAL; pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); @@ -101,7 +102,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) if (ifindex == 0) { struct rt6_info *rt; - rt = rt6_lookup(&init_net, addr, NULL, 0, 0); + rt = rt6_lookup(net, addr, NULL, 0, 0); if (rt) { dev = rt->rt6i_dev; dev_hold(dev); @@ -112,10 +113,10 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) } else { /* router, no matching interface: just pick one */ - dev = dev_get_by_flags(&init_net, IFF_UP, IFF_UP|IFF_LOOPBACK); + dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK); } } else - dev = dev_get_by_index(&init_net, ifindex); + dev = dev_get_by_index(net, ifindex); if (dev == NULL) { err = -ENODEV; @@ -176,6 +177,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev; struct ipv6_ac_socklist *pac, *prev_pac; + struct net *net = sock_net(sk); write_lock_bh(&ipv6_sk_ac_lock); prev_pac = NULL; @@ -196,7 +198,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) write_unlock_bh(&ipv6_sk_ac_lock); - dev = dev_get_by_index(&init_net, pac->acl_ifindex); + dev = dev_get_by_index(net, pac->acl_ifindex); if (dev) { ipv6_dev_ac_dec(dev, &pac->acl_addr); dev_put(dev); @@ -210,6 +212,7 @@ void ipv6_sock_ac_close(struct sock *sk) struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev = NULL; struct ipv6_ac_socklist *pac; + struct net *net = sock_net(sk); int prev_index; write_lock_bh(&ipv6_sk_ac_lock); @@ -224,7 +227,7 @@ void ipv6_sock_ac_close(struct sock *sk) if (pac->acl_ifindex != prev_index) { if (dev) dev_put(dev); - dev = dev_get_by_index(&init_net, pac->acl_ifindex); + dev = dev_get_by_index(net, pac->acl_ifindex); prev_index = pac->acl_ifindex; } if (dev) @@ -422,14 +425,15 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) /* * check if given interface (or any, if dev==0) has this anycast address */ -int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr) +int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, + struct in6_addr *addr) { int found = 0; if (dev) return ipv6_chk_acast_dev(dev, addr); read_lock(&dev_base_lock); - for_each_netdev(&init_net, dev) + for_each_netdev(net, dev) if (ipv6_chk_acast_dev(dev, addr)) { found = 1; break; @@ -441,6 +445,7 @@ int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr) #ifdef CONFIG_PROC_FS struct ac6_iter_state { + struct seq_net_private p; struct net_device *dev; struct inet6_dev *idev; }; @@ -451,9 +456,10 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq) { struct ifacaddr6 *im = NULL; struct ac6_iter_state *state = ac6_seq_private(seq); + struct net *net = seq_file_net(seq); state->idev = NULL; - for_each_netdev(&init_net, state->dev) { + for_each_netdev(net, state->dev) { struct inet6_dev *idev; idev = in6_dev_get(state->dev); if (!idev) @@ -551,8 +557,8 @@ static const struct seq_operations ac6_seq_ops = { static int ac6_seq_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &ac6_seq_ops, - sizeof(struct ac6_iter_state)); + return seq_open_net(inode, file, &ac6_seq_ops, + sizeof(struct ac6_iter_state)); } static const struct file_operations ac6_seq_fops = { @@ -560,20 +566,20 @@ static const struct file_operations ac6_seq_fops = { .open = ac6_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; -int __init ac6_proc_init(void) +int ac6_proc_init(struct net *net) { - if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops)) + if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops)) return -ENOMEM; return 0; } -void ac6_proc_exit(void) +void ac6_proc_exit(struct net *net) { - proc_net_remove(&init_net, "anycast6"); + proc_net_remove(net, "anycast6"); } #endif diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 79af57f586e8..b4d8e331432e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -773,7 +773,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) return; } - if (ipv6_chk_acast_addr(dev, &msg->target) || + if (ipv6_chk_acast_addr(dev_net(dev), dev, &msg->target) || (idev->cnf.forwarding && (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && (pneigh = pneigh_lookup(&nd_tbl, dev_net(dev), |