Commit d8a5ec672768c3cf4d51d7a63fc071520afa1617
Committed by
David S. Miller
1 parent
ce286d3273
Exists in
master
and in
39 other branches
[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
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; |