ipv6: allow nonlocal_bind for ipv6 addresses

Luis Henriques luis.henriques at canonical.com
Wed Jun 26 16:53:05 UTC 2013


Hi,

"Timh B" <timh at shiwebs.net> writes:

> Hi,
>
> We've encountered a problem when migrating services that uses vrrpd (for
> example) to IPv6 (dualstack), a nonlocal_bind problem to be exact, for
> IPv4 there's a sysctl-setting that allows us to bind to addresses that are
> not configured on the host directly.
>
> I'm aware that there's freebind and ip_transparent options to setsockopt()
> but changing all the services's code would have been a larger task than
> implementing the nonlocal_bind option for IPv6 in the kenrel.
>
> The patch is done for kernel 3.5, so for 3.2 (Ubuntu 12.04 LTS) the patch
> from Maciej Żenczykowski has to be applied first;
>
> https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/net/ipv6/af_inet6.c?id=f74024d9f05caa570dcf7582b498bbf011943491
>
> My patch is attached.

Although I can't assess the correctness of your patch, this is the
kind of changes I don't feel comfortable to see in the Ubuntu kernels
without being in mainline kernel.

>From your description, this is an upstream problem so I think you
should try to submit it to lkml (and netdev, I guess), possibly
tagging it for inclusion in stable kernels as well.

Cheers,
-- 
Luis

>
> Usage: sysctl -w net.ipv6.ip6_nonlocal_bind=1
>
> -- Timh
>
> From 44934986d09b6bd55023123b236e09db7a03778a Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Timh=20Bergstr=C3=B6m?= <timh at shiwebs.net>
> Date: Tue, 25 Jun 2013 12:43:00 +0200
> Subject: [PATCH] UBUNTU: SAUCE: Added ip_nonlocal_bind functionality for IPv6
>
> Signed-off-by: timh <timh at shiwebs.net>
>
> * Added sysctl for ipv6 equalivient of net.ipv4.ip_nonlocal_bind.
> * Added check in inet6_bind() for ip6_nonlocal_bind so we allow
>   binding to arbitrary IPv6 addresses on a host.
>
> Same weaknesses and strengths that exists for ip_nonlocal_bind apply
> on ip6_nonlocal_bind.
> ---
>  include/linux/sysctl.h     |    1 +
>  include/net/ipv6.h         |    2 ++
>  include/net/netns/ipv6.h   |    1 +
>  kernel/sysctl_binary.c     |    1 +
>  net/ipv6/af_inet6.c        |    9 +++++++--
>  net/ipv6/sysctl_net_ipv6.c |    7 +++++++
>  6 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index c34b4c8..7af300f 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -528,6 +528,7 @@ enum {
>  	NET_IPV6_IP6FRAG_TIME=23,
>  	NET_IPV6_IP6FRAG_SECRET_INTERVAL=24,
>  	NET_IPV6_MLD_MAX_MSF=25,
> +        NET_IPV6_NONLOCAL_BIND=30,
>  };
>  
>  enum {
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index c11fa5d..44fdad6 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -583,6 +583,8 @@ extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
>   *	socket options (ipv6_sockglue.c)
>   */
>  
> +extern int sysctl_ip6_nonlocal_bind;
> +
>  extern int			ipv6_setsockopt(struct sock *sk, int level, 
>  						int optname,
>  						char __user *optval, 
> diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
> index b42be53..cfc9486 100644
> --- a/include/net/netns/ipv6.h
> +++ b/include/net/netns/ipv6.h
> @@ -18,6 +18,7 @@ struct netns_sysctl_ipv6 {
>  	struct ctl_table_header *frags_hdr;
>  #endif
>  	int bindv6only;
> +        int ip6_nonlocal_bind;
>  	int flush_delay;
>  	int ip6_rt_max_size;
>  	int ip6_rt_gc_min_interval;
> diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
> index 9f9aa32..b611831 100644
> --- a/kernel/sysctl_binary.c
> +++ b/kernel/sysctl_binary.c
> @@ -558,6 +558,7 @@ static const struct bin_table bin_net_ipv6_table[] = {
>  	{ CTL_DIR,	NET_IPV6_ROUTE,		"route",	bin_net_ipv6_route_table },
>  	{ CTL_DIR,	NET_IPV6_ICMP,		"icmp",		bin_net_ipv6_icmp_table },
>  	{ CTL_INT,	NET_IPV6_BINDV6ONLY,		"bindv6only" },
> +        { CTL_INT,      NET_IPV6_NONLOCAL_BIND,         "ip6_nonlocal_bind" },
>  	{ CTL_INT,	NET_IPV6_IP6FRAG_HIGH_THRESH,	"ip6frag_high_thresh" },
>  	{ CTL_INT,	NET_IPV6_IP6FRAG_LOW_THRESH,	"ip6frag_low_thresh" },
>  	{ CTL_INT,	NET_IPV6_IP6FRAG_TIME,		"ip6frag_time" },
> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> index e22e6d8..55dd5be 100644
> --- a/net/ipv6/af_inet6.c
> +++ b/net/ipv6/af_inet6.c
> @@ -255,6 +255,9 @@ out_rcu_unlock:
>  
>  
>  /* bind for INET6 API */
> +int sysctl_ip6_nonlocal_bind __read_mostly;
> +EXPORT_SYMBOL(sysctl_ip6_nonlocal_bind);
> +
>  int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
>  {
>  	struct sockaddr_in6 *addr = (struct sockaddr_in6 *)uaddr;
> @@ -308,7 +311,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
>  		/* Reproduce AF_INET checks to make the bindings consistent */
>  		v4addr = addr->sin6_addr.s6_addr32[3];
>  		chk_addr_ret = inet_addr_type(net, v4addr);
> -		if (!sysctl_ip_nonlocal_bind &&
> +		if (!sysctl_ip6_nonlocal_bind &&
>  		    !(inet->freebind || inet->transparent) &&
>  		    v4addr != htonl(INADDR_ANY) &&
>  		    chk_addr_ret != RTN_LOCAL &&
> @@ -348,7 +351,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 (!sysctl_ip6_nonlocal_bind &&
> +                                !(inet->freebind || inet->transparent) &&
>  				    !ipv6_chk_addr(net, &addr->sin6_addr,
>  						   dev, 0)) {
>  					err = -EADDRNOTAVAIL;
> @@ -1008,6 +1012,7 @@ static int __net_init inet6_net_init(struct net *net)
>  	int err = 0;
>  
>  	net->ipv6.sysctl.bindv6only = 0;
> +        net->ipv6.sysctl.ip6_nonlocal_bind = 0;
>  	net->ipv6.sysctl.icmpv6_time = 1*HZ;
>  
>  	err = ipv6_init_mibs(net);
> diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
> index e85c48b..87699ca 100644
> --- a/net/ipv6/sysctl_net_ipv6.c
> +++ b/net/ipv6/sysctl_net_ipv6.c
> @@ -24,6 +24,13 @@ static ctl_table ipv6_table_template[] = {
>  		.mode		= 0644,
>  		.proc_handler	= proc_dointvec
>  	},
> +        {
> +                .procname       = "ip6_nonlocal_bind",
> +                .data           = &sysctl_ip6_nonlocal_bind,
> +                .maxlen         = sizeof(int),
> +                .mode           = 0644,
> +                .proc_handler   = proc_dointvec
> +        },
>  	{ }
>  };
>  
> -- 
> 1.7.9.5




More information about the kernel-team mailing list