[NET]: netlink support for moving devices between network namespaces.

The simplest thing to implement is moving network devices between
namespaces.  However with the same attribute IFLA_NET_NS_PID we can
easily implement creating devices in the destination network
namespace as well.  However that is a little bit trickier so this
patch sticks to what is simple and easy.

A pid is used to identify a process that happens to be a member
of the network namespace we want to move the network device to.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Eric W. Biederman 2007-09-12 13:57:04 +02:00 коммит произвёл David S. Miller
Родитель ce286d3273
Коммит d8a5ec6727
2 изменённых файлов: 36 добавлений и 0 удалений

Просмотреть файл

@ -78,6 +78,7 @@ enum
IFLA_LINKMODE, IFLA_LINKMODE,
IFLA_LINKINFO, IFLA_LINKINFO,
#define IFLA_LINKINFO IFLA_LINKINFO #define IFLA_LINKINFO IFLA_LINKINFO
IFLA_NET_NS_PID,
__IFLA_MAX __IFLA_MAX
}; };

Просмотреть файл

@ -35,6 +35,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/if_addr.h> #include <linux/if_addr.h>
#include <linux/nsproxy.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
@ -727,6 +728,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_WEIGHT] = { .type = NLA_U32 }, [IFLA_WEIGHT] = { .type = NLA_U32 },
[IFLA_OPERSTATE] = { .type = NLA_U8 }, [IFLA_OPERSTATE] = { .type = NLA_U8 },
[IFLA_LINKMODE] = { .type = NLA_U8 }, [IFLA_LINKMODE] = { .type = NLA_U8 },
[IFLA_NET_NS_PID] = { .type = NLA_U32 },
}; };
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@ -734,12 +736,45 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
[IFLA_INFO_DATA] = { .type = NLA_NESTED }, [IFLA_INFO_DATA] = { .type = NLA_NESTED },
}; };
static struct net *get_net_ns_by_pid(pid_t pid)
{
struct task_struct *tsk;
struct net *net;
/* Lookup the network namespace */
net = ERR_PTR(-ESRCH);
rcu_read_lock();
tsk = find_task_by_pid(pid);
if (tsk) {
task_lock(tsk);
if (tsk->nsproxy)
net = get_net(tsk->nsproxy->net_ns);
task_unlock(tsk);
}
rcu_read_unlock();
return net;
}
static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
struct nlattr **tb, char *ifname, int modified) struct nlattr **tb, char *ifname, int modified)
{ {
int send_addr_notify = 0; int send_addr_notify = 0;
int err; int err;
if (tb[IFLA_NET_NS_PID]) {
struct net *net;
net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
if (IS_ERR(net)) {
err = PTR_ERR(net);
goto errout;
}
err = dev_change_net_namespace(dev, net, ifname);
put_net(net);
if (err)
goto errout;
modified = 1;
}
if (tb[IFLA_MAP]) { if (tb[IFLA_MAP]) {
struct rtnl_link_ifmap *u_map; struct rtnl_link_ifmap *u_map;
struct ifmap k_map; struct ifmap k_map;