forked from mirrors/linux
		
	[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:
		
							parent
							
								
									ce286d3273
								
							
						
					
					
						commit
						d8a5ec6727
					
				
					 2 changed files with 36 additions and 0 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue