aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2015-07-08 19:58:22 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-10 00:09:10 -0400
commit35a256fee52c7c207796302681fa95189c85b408 (patch)
treec6f4e37117bfe3423b095e55073d9c2ed337c176
parent5a10ececc60c469d0641531589ccc38a768e0d07 (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.txt5
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--net/ipv4/ping.c3
-rw-r--r--net/ipv6/af_inet6.c3
-rw-r--r--net/ipv6/raw.c3
-rw-r--r--net/ipv6/sysctl_net_ipv6.c8
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
1438ip_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
1438router_probe_interval - INTEGER 1443router_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)