forked from mirrors/linux
		
	ipv6: Nonlocal bind
Add support to allow non-local binds similar to how this was done for IPv4. Non-local binds are very useful in emulating the Internet in a box, etc. This add the ip_nonlocal_bind sysctl under ipv6. Testing: Set up nonlocal binding and receive routing on a host, e.g.: ip -6 rule add from ::/0 iif eth0 lookup 200 ip -6 route add local 2001:0:0:1::/64 dev lo proto kernel scope host table 200 sysctl -w net.ipv6.ip_nonlocal_bind=1 Set up routing to 2001:0:0:1::/64 on peer to go to first host ping6 -I 2001:0:0:1::1 peer-address -- to verify Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5a10ececc6
								
							
						
					
					
						commit
						35a256fee5
					
				
					 6 changed files with 20 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -1435,6 +1435,11 @@ mtu - INTEGER
 | 
			
		|||
	Default Maximum Transfer Unit
 | 
			
		||||
	Default: 1280 (IPv6 required minimum)
 | 
			
		||||
 | 
			
		||||
ip_nonlocal_bind - BOOLEAN
 | 
			
		||||
	If set, allows processes to bind() to non-local IPv6 addresses,
 | 
			
		||||
	which can be quite useful - but may break some applications.
 | 
			
		||||
	Default: 0
 | 
			
		||||
 | 
			
		||||
router_probe_interval - INTEGER
 | 
			
		||||
	Minimum interval (in seconds) between Router Probing described
 | 
			
		||||
	in RFC4191.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ struct netns_sysctl_ipv6 {
 | 
			
		|||
	int auto_flowlabels;
 | 
			
		||||
	int icmpv6_time;
 | 
			
		||||
	int anycast_src_echo_reply;
 | 
			
		||||
	int ip_nonlocal_bind;
 | 
			
		||||
	int fwmark_reflect;
 | 
			
		||||
	int idgen_retries;
 | 
			
		||||
	int idgen_delay;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -363,7 +363,8 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
 | 
			
		|||
						    scoped);
 | 
			
		||||
		rcu_read_unlock();
 | 
			
		||||
 | 
			
		||||
		if (!(isk->freebind || isk->transparent || has_addr ||
 | 
			
		||||
		if (!(net->ipv6.sysctl.ip_nonlocal_bind ||
 | 
			
		||||
		      isk->freebind || isk->transparent || has_addr ||
 | 
			
		||||
		      addr_type == IPV6_ADDR_ANY))
 | 
			
		||||
			return -EADDRNOTAVAIL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -342,7 +342,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 | 
			
		|||
			 */
 | 
			
		||||
			v4addr = LOOPBACK4_IPV6;
 | 
			
		||||
			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
 | 
			
		||||
				if (!(inet->freebind || inet->transparent) &&
 | 
			
		||||
				if (!net->ipv6.sysctl.ip_nonlocal_bind &&
 | 
			
		||||
				    !(inet->freebind || inet->transparent) &&
 | 
			
		||||
				    !ipv6_chk_addr(net, &addr->sin6_addr,
 | 
			
		||||
						   dev, 0)) {
 | 
			
		||||
					err = -EADDRNOTAVAIL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -295,7 +295,8 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 | 
			
		|||
		 * unspecified and mapped address have a v4 equivalent.
 | 
			
		||||
		 */
 | 
			
		||||
		v4addr = LOOPBACK4_IPV6;
 | 
			
		||||
		if (!(addr_type & IPV6_ADDR_MULTICAST))	{
 | 
			
		||||
		if (!(addr_type & IPV6_ADDR_MULTICAST) &&
 | 
			
		||||
		    !sock_net(sk)->ipv6.sysctl.ip_nonlocal_bind) {
 | 
			
		||||
			err = -EADDRNOTAVAIL;
 | 
			
		||||
			if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
 | 
			
		||||
					   dev, 0)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,6 +75,13 @@ static struct ctl_table ipv6_table_template[] = {
 | 
			
		|||
		.mode		= 0644,
 | 
			
		||||
		.proc_handler	= proc_dointvec
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.procname	= "ip_nonlocal_bind",
 | 
			
		||||
		.data		= &init_net.ipv6.sysctl.ip_nonlocal_bind,
 | 
			
		||||
		.maxlen		= sizeof(int),
 | 
			
		||||
		.mode		= 0644,
 | 
			
		||||
		.proc_handler	= proc_dointvec
 | 
			
		||||
	},
 | 
			
		||||
	{ }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -117,6 +124,7 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
 | 
			
		|||
	ipv6_table[5].data = &net->ipv6.sysctl.idgen_retries;
 | 
			
		||||
	ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay;
 | 
			
		||||
	ipv6_table[7].data = &net->ipv6.sysctl.flowlabel_state_ranges;
 | 
			
		||||
	ipv6_table[8].data = &net->ipv6.sysctl.ip_nonlocal_bind;
 | 
			
		||||
 | 
			
		||||
	ipv6_route_table = ipv6_route_sysctl_init(net);
 | 
			
		||||
	if (!ipv6_route_table)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue