Skip to content

Commit

Permalink
net: Allow setting the network namespace by fd
Browse files Browse the repository at this point in the history
Take advantage of the new abstraction and allow network devices
to be placed in any network namespace that we have a fd to talk
about.

Acked-by: David S. Miller <[email protected]>
Acked-by: Daniel Lezcano <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
  • Loading branch information
ebiederm committed May 10, 2011
1 parent a00eaf1 commit f063052
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/linux/if_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ enum {
IFLA_PORT_SELF,
IFLA_AF_SPEC,
IFLA_GROUP, /* Group the device belongs to */
IFLA_NET_NS_FD,
__IFLA_MAX
};

Expand Down
1 change: 1 addition & 0 deletions include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
extern struct list_head net_namespace_list;

extern struct net *get_net_ns_by_pid(pid_t pid);
extern struct net *get_net_ns_by_fd(int pid);

#ifdef CONFIG_NET_NS
extern void __put_net(struct net *net);
Expand Down
33 changes: 31 additions & 2 deletions net/core/net_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <linux/idr.h>
#include <linux/rculist.h>
#include <linux/nsproxy.h>
#include <linux/proc_fs.h>
#include <linux/file.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>

Expand Down Expand Up @@ -343,6 +345,28 @@ struct net *get_net_ns_by_pid(pid_t pid)
}
EXPORT_SYMBOL_GPL(get_net_ns_by_pid);

struct net *get_net_ns_by_fd(int fd)
{
struct proc_inode *ei;
struct file *file;
struct net *net;

net = ERR_PTR(-EINVAL);
file = proc_ns_fget(fd);
if (!file)
goto out;

ei = PROC_I(file->f_dentry->d_inode);
if (ei->ns_ops != &netns_operations)
goto out;

net = get_net(ei->ns);
out:
if (file)
fput(file);
return net;
}

static int __init net_ns_init(void)
{
struct net_generic *ng;
Expand Down Expand Up @@ -577,10 +601,15 @@ EXPORT_SYMBOL_GPL(unregister_pernet_device);
#ifdef CONFIG_NET_NS
static void *netns_get(struct task_struct *task)
{
struct net *net;
struct net *net = NULL;
struct nsproxy *nsproxy;

rcu_read_lock();
net = get_net(task->nsproxy->net_ns);
nsproxy = task_nsproxy(task);
if (nsproxy)
net = get_net(nsproxy->net_ns);
rcu_read_unlock();

return net;
}

Expand Down
5 changes: 4 additions & 1 deletion net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_LINKMODE] = { .type = NLA_U8 },
[IFLA_LINKINFO] = { .type = NLA_NESTED },
[IFLA_NET_NS_PID] = { .type = NLA_U32 },
[IFLA_NET_NS_FD] = { .type = NLA_U32 },
[IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
[IFLA_VFINFO_LIST] = {. type = NLA_NESTED },
[IFLA_VF_PORTS] = { .type = NLA_NESTED },
Expand Down Expand Up @@ -1091,6 +1092,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
*/
if (tb[IFLA_NET_NS_PID])
net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
else if (tb[IFLA_NET_NS_FD])
net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
else
net = get_net(src_net);
return net;
Expand Down Expand Up @@ -1221,7 +1224,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
int send_addr_notify = 0;
int err;

if (tb[IFLA_NET_NS_PID]) {
if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
struct net *net = rtnl_link_get_net(dev_net(dev), tb);
if (IS_ERR(net)) {
err = PTR_ERR(net);
Expand Down

0 comments on commit f063052

Please sign in to comment.