Commit d8a5ec672768c3cf4d51d7a63fc071520afa1617

Authored by Eric W. Biederman
Committed by David S. Miller
1 parent ce286d3273

[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>

Showing 2 changed files with 36 additions and 0 deletions Side-by-side Diff

include/linux/if_link.h
... ... @@ -78,6 +78,7 @@
78 78 IFLA_LINKMODE,
79 79 IFLA_LINKINFO,
80 80 #define IFLA_LINKINFO IFLA_LINKINFO
  81 + IFLA_NET_NS_PID,
81 82 __IFLA_MAX
82 83 };
83 84  
net/core/rtnetlink.c
... ... @@ -35,6 +35,7 @@
35 35 #include <linux/security.h>
36 36 #include <linux/mutex.h>
37 37 #include <linux/if_addr.h>
  38 +#include <linux/nsproxy.h>
38 39  
39 40 #include <asm/uaccess.h>
40 41 #include <asm/system.h>
... ... @@ -727,6 +728,7 @@
727 728 [IFLA_WEIGHT] = { .type = NLA_U32 },
728 729 [IFLA_OPERSTATE] = { .type = NLA_U8 },
729 730 [IFLA_LINKMODE] = { .type = NLA_U8 },
  731 + [IFLA_NET_NS_PID] = { .type = NLA_U32 },
730 732 };
731 733  
732 734 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
733 735  
... ... @@ -734,11 +736,44 @@
734 736 [IFLA_INFO_DATA] = { .type = NLA_NESTED },
735 737 };
736 738  
  739 +static struct net *get_net_ns_by_pid(pid_t pid)
  740 +{
  741 + struct task_struct *tsk;
  742 + struct net *net;
  743 +
  744 + /* Lookup the network namespace */
  745 + net = ERR_PTR(-ESRCH);
  746 + rcu_read_lock();
  747 + tsk = find_task_by_pid(pid);
  748 + if (tsk) {
  749 + task_lock(tsk);
  750 + if (tsk->nsproxy)
  751 + net = get_net(tsk->nsproxy->net_ns);
  752 + task_unlock(tsk);
  753 + }
  754 + rcu_read_unlock();
  755 + return net;
  756 +}
  757 +
737 758 static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
738 759 struct nlattr **tb, char *ifname, int modified)
739 760 {
740 761 int send_addr_notify = 0;
741 762 int err;
  763 +
  764 + if (tb[IFLA_NET_NS_PID]) {
  765 + struct net *net;
  766 + net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
  767 + if (IS_ERR(net)) {
  768 + err = PTR_ERR(net);
  769 + goto errout;
  770 + }
  771 + err = dev_change_net_namespace(dev, net, ifname);
  772 + put_net(net);
  773 + if (err)
  774 + goto errout;
  775 + modified = 1;
  776 + }
742 777  
743 778 if (tb[IFLA_MAP]) {
744 779 struct rtnl_link_ifmap *u_map;