Skip to content

Commit

Permalink
ipv6: Nonlocal bind
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tom Herbert authored and David S. Miller committed Jul 10, 2015
1 parent 5a10ece commit 35a256f
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 3 deletions.
5 changes: 5 additions & 0 deletions Documentation/networking/ip-sysctl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions include/net/netns/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion net/ipv4/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion net/ipv6/af_inet6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion net/ipv6/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
8 changes: 8 additions & 0 deletions net/ipv6/sysctl_net_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
{ }
};

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 35a256f

Please sign in to comment.