diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
| -rw-r--r-- | net/ipv6/addrconf.c | 40 | 
1 files changed, 38 insertions, 2 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4ab4c38958c..cec8cb4d292 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -198,6 +198,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {  	.accept_ra_rt_info_max_plen = 0,  #endif  #endif +	.accept_ra_rt_table	= 0,  	.proxy_ndp		= 0,  	.accept_source_route	= 0,	/* we do not accept RH0 by default. */  	.disable_ipv6		= 0, @@ -232,6 +233,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {  	.accept_ra_rt_info_max_plen = 0,  #endif  #endif +	.accept_ra_rt_table	= 0,  	.proxy_ndp		= 0,  	.accept_source_route	= 0,	/* we do not accept RH0 by default. */  	.disable_ipv6		= 0, @@ -1910,6 +1912,31 @@ static void  __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmp  }  #endif +u32 addrconf_rt_table(const struct net_device *dev, u32 default_table) { +	/* Determines into what table to put autoconf PIO/RIO/default routes +	 * learned on this device. +	 * +	 * - If 0, use the same table for every device. This puts routes into +	 *   one of RT_TABLE_{PREFIX,INFO,DFLT} depending on the type of route +	 *   (but note that these three are currently all equal to +	 *   RT6_TABLE_MAIN). +	 * - If > 0, use the specified table. +	 * - If < 0, put routes into table dev->ifindex + (-rt_table). +	 */ +	struct inet6_dev *idev = in6_dev_get(dev); +	u32 table; +	int sysctl = idev->cnf.accept_ra_rt_table; +	if (sysctl == 0) { +		table = default_table; +	} else if (sysctl > 0) { +		table = (u32) sysctl; +	} else { +		table = (unsigned) dev->ifindex + (-sysctl); +	} +	in6_dev_put(idev); +	return table; +} +  /*   *	Add prefix route.   */ @@ -1919,7 +1946,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,  		      unsigned long expires, u32 flags)  {  	struct fib6_config cfg = { -		.fc_table = RT6_TABLE_PREFIX, +		.fc_table = addrconf_rt_table(dev, RT6_TABLE_PREFIX),  		.fc_metric = IP6_RT_PRIO_ADDRCONF,  		.fc_ifindex = dev->ifindex,  		.fc_expires = expires, @@ -1953,7 +1980,8 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,  	struct rt6_info *rt = NULL;  	struct fib6_table *table; -	table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX); +	table = fib6_get_table(dev_net(dev), +			       addrconf_rt_table(dev, RT6_TABLE_PREFIX));  	if (table == NULL)  		return NULL; @@ -4159,6 +4187,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,  	array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;  #endif  #endif +	array[DEVCONF_ACCEPT_RA_RT_TABLE] = cnf->accept_ra_rt_table;  	array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;  	array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;  #ifdef CONFIG_IPV6_OPTIMISTIC_DAD @@ -4868,6 +4897,13 @@ static struct addrconf_sysctl_table  #endif  #endif  		{ +			.procname	= "accept_ra_rt_table", +			.data		= &ipv6_devconf.accept_ra_rt_table, +			.maxlen		= sizeof(int), +			.mode		= 0644, +			.proc_handler	= proc_dointvec, +		}, +		{  			.procname	= "proxy_ndp",  			.data		= &ipv6_devconf.proxy_ndp,  			.maxlen		= sizeof(int),  |