diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2007-09-12 07:57:04 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:49:13 -0400 |
commit | d8a5ec672768c3cf4d51d7a63fc071520afa1617 (patch) | |
tree | 16401b29340732fa37de7899fc44db6b682e20d7 /net | |
parent | ce286d327341295f58d89864d746a524287cfdf9 (diff) |
[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>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/rtnetlink.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 44f91bb1ae8d..1b9c32d79917 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/security.h> | 35 | #include <linux/security.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/if_addr.h> | 37 | #include <linux/if_addr.h> |
38 | #include <linux/nsproxy.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/system.h> | 41 | #include <asm/system.h> |
@@ -727,6 +728,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
727 | [IFLA_WEIGHT] = { .type = NLA_U32 }, | 728 | [IFLA_WEIGHT] = { .type = NLA_U32 }, |
728 | [IFLA_OPERSTATE] = { .type = NLA_U8 }, | 729 | [IFLA_OPERSTATE] = { .type = NLA_U8 }, |
729 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 730 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
731 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | ||
730 | }; | 732 | }; |
731 | 733 | ||
732 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 734 | 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] = { | |||
734 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, | 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 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | 758 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
738 | struct nlattr **tb, char *ifname, int modified) | 759 | struct nlattr **tb, char *ifname, int modified) |
739 | { | 760 | { |
740 | int send_addr_notify = 0; | 761 | int send_addr_notify = 0; |
741 | int err; | 762 | int err; |
742 | 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 | } | ||
777 | |||
743 | if (tb[IFLA_MAP]) { | 778 | if (tb[IFLA_MAP]) { |
744 | struct rtnl_link_ifmap *u_map; | 779 | struct rtnl_link_ifmap *u_map; |
745 | struct ifmap k_map; | 780 | struct ifmap k_map; |