diff options
author | Tom Herbert <tom@herbertland.com> | 2015-07-08 19:58:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-10 00:09:10 -0400 |
commit | 35a256fee52c7c207796302681fa95189c85b408 (patch) | |
tree | c6f4e37117bfe3423b095e55073d9c2ed337c176 | |
parent | 5a10ececc60c469d0641531589ccc38a768e0d07 (diff) |
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>
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 5 | ||||
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv4/ping.c | 3 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 3 | ||||
-rw-r--r-- | net/ipv6/raw.c | 3 | ||||
-rw-r--r-- | net/ipv6/sysctl_net_ipv6.c | 8 |
6 files changed, 20 insertions, 3 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 5fae7704daab..f63aeefd2c24 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -1435,6 +1435,11 @@ mtu - INTEGER | |||
1435 | Default Maximum Transfer Unit | 1435 | Default Maximum Transfer Unit |
1436 | Default: 1280 (IPv6 required minimum) | 1436 | Default: 1280 (IPv6 required minimum) |
1437 | 1437 | ||
1438 | ip_nonlocal_bind - BOOLEAN | ||
1439 | If set, allows processes to bind() to non-local IPv6 addresses, | ||
1440 | which can be quite useful - but may break some applications. | ||
1441 | Default: 0 | ||
1442 | |||
1438 | router_probe_interval - INTEGER | 1443 | router_probe_interval - INTEGER |
1439 | Minimum interval (in seconds) between Router Probing described | 1444 | Minimum interval (in seconds) between Router Probing described |
1440 | in RFC4191. | 1445 | in RFC4191. |
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 8d93544a2d2b..c0368db6df54 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -31,6 +31,7 @@ struct netns_sysctl_ipv6 { | |||
31 | int auto_flowlabels; | 31 | int auto_flowlabels; |
32 | int icmpv6_time; | 32 | int icmpv6_time; |
33 | int anycast_src_echo_reply; | 33 | int anycast_src_echo_reply; |
34 | int ip_nonlocal_bind; | ||
34 | int fwmark_reflect; | 35 | int fwmark_reflect; |
35 | int idgen_retries; | 36 | int idgen_retries; |
36 | int idgen_delay; | 37 | int idgen_delay; |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 05ff44b758df..e89094ab5ddb 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -363,7 +363,8 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, | |||
363 | scoped); | 363 | scoped); |
364 | rcu_read_unlock(); | 364 | rcu_read_unlock(); |
365 | 365 | ||
366 | if (!(isk->freebind || isk->transparent || has_addr || | 366 | if (!(net->ipv6.sysctl.ip_nonlocal_bind || |
367 | isk->freebind || isk->transparent || has_addr || | ||
367 | addr_type == IPV6_ADDR_ANY)) | 368 | addr_type == IPV6_ADDR_ANY)) |
368 | return -EADDRNOTAVAIL; | 369 | return -EADDRNOTAVAIL; |
369 | 370 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 39e670a91596..7bc92ea4ae8f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -342,7 +342,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
342 | */ | 342 | */ |
343 | v4addr = LOOPBACK4_IPV6; | 343 | v4addr = LOOPBACK4_IPV6; |
344 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 344 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
345 | if (!(inet->freebind || inet->transparent) && | 345 | if (!net->ipv6.sysctl.ip_nonlocal_bind && |
346 | !(inet->freebind || inet->transparent) && | ||
346 | !ipv6_chk_addr(net, &addr->sin6_addr, | 347 | !ipv6_chk_addr(net, &addr->sin6_addr, |
347 | dev, 0)) { | 348 | dev, 0)) { |
348 | err = -EADDRNOTAVAIL; | 349 | err = -EADDRNOTAVAIL; |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ca4700cb26c4..fdbada1569a3 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -295,7 +295,8 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
295 | * unspecified and mapped address have a v4 equivalent. | 295 | * unspecified and mapped address have a v4 equivalent. |
296 | */ | 296 | */ |
297 | v4addr = LOOPBACK4_IPV6; | 297 | v4addr = LOOPBACK4_IPV6; |
298 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 298 | if (!(addr_type & IPV6_ADDR_MULTICAST) && |
299 | !sock_net(sk)->ipv6.sysctl.ip_nonlocal_bind) { | ||
299 | err = -EADDRNOTAVAIL; | 300 | err = -EADDRNOTAVAIL; |
300 | if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, | 301 | if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, |
301 | dev, 0)) { | 302 | dev, 0)) { |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 4e705add4f18..db48aebd9c47 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -75,6 +75,13 @@ static struct ctl_table ipv6_table_template[] = { | |||
75 | .mode = 0644, | 75 | .mode = 0644, |
76 | .proc_handler = proc_dointvec | 76 | .proc_handler = proc_dointvec |
77 | }, | 77 | }, |
78 | { | ||
79 | .procname = "ip_nonlocal_bind", | ||
80 | .data = &init_net.ipv6.sysctl.ip_nonlocal_bind, | ||
81 | .maxlen = sizeof(int), | ||
82 | .mode = 0644, | ||
83 | .proc_handler = proc_dointvec | ||
84 | }, | ||
78 | { } | 85 | { } |
79 | }; | 86 | }; |
80 | 87 | ||
@@ -117,6 +124,7 @@ static int __net_init ipv6_sysctl_net_init(struct net *net) | |||
117 | ipv6_table[5].data = &net->ipv6.sysctl.idgen_retries; | 124 | ipv6_table[5].data = &net->ipv6.sysctl.idgen_retries; |
118 | ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay; | 125 | ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay; |
119 | ipv6_table[7].data = &net->ipv6.sysctl.flowlabel_state_ranges; | 126 | ipv6_table[7].data = &net->ipv6.sysctl.flowlabel_state_ranges; |
127 | ipv6_table[8].data = &net->ipv6.sysctl.ip_nonlocal_bind; | ||
120 | 128 | ||
121 | ipv6_route_table = ipv6_route_sysctl_init(net); | 129 | ipv6_route_table = ipv6_route_sysctl_init(net); |
122 | if (!ipv6_route_table) | 130 | if (!ipv6_route_table) |