diff options
-rw-r--r-- | include/linux/if_link.h | 1 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 35 |
2 files changed, 36 insertions, 0 deletions
diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 422084d18ce1..84c3492ae5cb 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h | |||
@@ -78,6 +78,7 @@ enum | |||
78 | IFLA_LINKMODE, | 78 | IFLA_LINKMODE, |
79 | IFLA_LINKINFO, | 79 | IFLA_LINKINFO, |
80 | #define IFLA_LINKINFO IFLA_LINKINFO | 80 | #define IFLA_LINKINFO IFLA_LINKINFO |
81 | IFLA_NET_NS_PID, | ||
81 | __IFLA_MAX | 82 | __IFLA_MAX |
82 | }; | 83 | }; |
83 | 84 | ||
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; |