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
|
@ -1435,6 +1435,11 @@ mtu - INTEGER
|
||||||
Default Maximum Transfer Unit
|
Default Maximum Transfer Unit
|
||||||
Default: 1280 (IPv6 required minimum)
|
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
|
router_probe_interval - INTEGER
|
||||||
Minimum interval (in seconds) between Router Probing described
|
Minimum interval (in seconds) between Router Probing described
|
||||||
in RFC4191.
|
in RFC4191.
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct netns_sysctl_ipv6 {
|
||||||
int auto_flowlabels;
|
int auto_flowlabels;
|
||||||
int icmpv6_time;
|
int icmpv6_time;
|
||||||
int anycast_src_echo_reply;
|
int anycast_src_echo_reply;
|
||||||
|
int ip_nonlocal_bind;
|
||||||
int fwmark_reflect;
|
int fwmark_reflect;
|
||||||
int idgen_retries;
|
int idgen_retries;
|
||||||
int idgen_delay;
|
int idgen_delay;
|
||||||
|
|
|
@ -363,7 +363,8 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
|
||||||
scoped);
|
scoped);
|
||||||
rcu_read_unlock();
|
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))
|
addr_type == IPV6_ADDR_ANY))
|
||||||
return -EADDRNOTAVAIL;
|
return -EADDRNOTAVAIL;
|
||||||
|
|
||||||
|
|
|
@ -342,7 +342,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||||
*/
|
*/
|
||||||
v4addr = LOOPBACK4_IPV6;
|
v4addr = LOOPBACK4_IPV6;
|
||||||
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
|
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,
|
!ipv6_chk_addr(net, &addr->sin6_addr,
|
||||||
dev, 0)) {
|
dev, 0)) {
|
||||||
err = -EADDRNOTAVAIL;
|
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.
|
* unspecified and mapped address have a v4 equivalent.
|
||||||
*/
|
*/
|
||||||
v4addr = LOOPBACK4_IPV6;
|
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;
|
err = -EADDRNOTAVAIL;
|
||||||
if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
|
if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
|
||||||
dev, 0)) {
|
dev, 0)) {
|
||||||
|
|
|
@ -75,6 +75,13 @@ static struct ctl_table ipv6_table_template[] = {
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec
|
.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[5].data = &net->ipv6.sysctl.idgen_retries;
|
||||||
ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay;
|
ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay;
|
||||||
ipv6_table[7].data = &net->ipv6.sysctl.flowlabel_state_ranges;
|
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);
|
ipv6_route_table = ipv6_route_sysctl_init(net);
|
||||||
if (!ipv6_route_table)
|
if (!ipv6_route_table)
|
||||||
|
|
Loading…
Reference in New Issue