2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 14:25:49 +00:00

inet: set IP_FREEBIND before binding socket to an ipv6 address (v2)

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@gmail.com>
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Andrew Vagin
2015-11-19 17:48:22 +03:00
committed by Pavel Emelyanov
parent c9a61a205f
commit 73a739b8d3

View File

@@ -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;
}
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;
}