[CRIU] [PATCH 2/2] inet: set IP_FREEBIND before binding socket to an ipv6 address (v2)

Pavel Emelyanov xemul at parallels.com
Fri Nov 20 10:16:58 PST 2015


On 11/19/2015 05:48 PM, Andrey Vagin wrote:
> From: Andrew Vagin <avagin at openvz.org>
> 
> When we restore ipv6 addresses, they go through a “tentative” phase
> and sockets could not be bound to them in this moment.
> 
> v2: add more comments in code
> 
> Reported-by: Ross Boucher <boucher at gmail.com>
> Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
> ---
>  sk-inet.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/sk-inet.c b/sk-inet.c
> index 65f103d..01383e8 100644
> --- a/sk-inet.c
> +++ b/sk-inet.c
> @@ -634,17 +634,50 @@ static int restore_sockaddr(union sockaddr_inet *sa,
>  
>  int inet_bind(int sk, struct inet_sk_info *ii)
>  {
> +	bool rst_freebind = false;
>  	union sockaddr_inet addr;
>  	int addr_size;
>  
>  	addr_size = restore_sockaddr(&addr, ii->ie->family,
>  			ii->ie->src_port, ii->ie->src_addr);
>  
> +	/*
> +	 * ipv6 addresses go through a “tentative” phase and
> +	 * sockets could not be bound to them in this moment
> +	 * without setting IP_FREEBIND.
> +	 */
> +	if (ii->ie->family == AF_INET6) {
> +		int yes = 1;
> +
> +		if (restore_opt(sk, SOL_IP, IP_FREEBIND, &yes))
> +			return -1;
> +
> +		if (ii->ie->ip_opts && ii->ie->ip_opts->freebind)
> +			/*
> +			 * The right value is already set, so
> +			 * don't need to restore it in restore_ip_opts()
> +			 */
> +			ii->ie->ip_opts->has_freebind = false;
> +		else
> +			rst_freebind = true;

Still don't get this logic. It says that

If the socket is ipv6 and has freebind set, then we just skip it (set
has_freebind to false and leave rst_freebind to false).

If the socket is ipv6 and does NOT have freebind set we force it to
OFF below and that's it.

Why?

> +	}
> +
>  	if (bind(sk, (struct sockaddr *)&addr, addr_size) == -1) {
>  		pr_perror("Can't bind inet socket");
>  		return -1;
>  	}
>  
> +	if (rst_freebind) {
> +		int no = 0;
> +
> +		/*
> +		 * The "no" value is default, so it will not be
> +		 * restore in restore_ip_opts()
> +		 */
> +		if (restore_opt(sk, SOL_IP, IP_FREEBIND, &no))
> +			return -1;
> +	}
> +
>  	return 0;
>  }
>  
> 



More information about the CRIU mailing list