[CRIU] [PATCH 2/2] inet: set IP_FREEBIND before binding socket to an ipv6 address
Andrey Vagin
avagin at openvz.org
Wed Nov 18 07:58:10 PST 2015
From: Andrew Vagin <avagin at virtuozzo.com>
When we restore ipv6 addresses, they go through a “tentative” phase
and sockets could not be bound to them in this moment.
Reported-by: Ross Boucher <boucher at gmail.com>
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
sk-inet.c | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/sk-inet.c b/sk-inet.c
index 779a1bd..a973000 100644
--- a/sk-inet.c
+++ b/sk-inet.c
@@ -633,17 +633,29 @@ 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;
- int val;
addr_size = restore_sockaddr(&addr, ii->ie->family,
ii->ie->src_port, ii->ie->src_addr);
- val = 1;
- if (setsockopt(sk, SOL_IP, IP_FREEBIND, &val, sizeof(int))) {
- pr_perror("Unable to set IP_FREEBIND");
- return -1;
+ /*
+ * 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)
+ /* don't restore freebind in restore_ip_opts() */
+ ii->ie->ip_opts->has_freebind = false;
+ else
+ rst_freebind = true;
}
if (bind(sk, (struct sockaddr *)&addr, addr_size) == -1) {
@@ -651,6 +663,13 @@ int inet_bind(int sk, struct inet_sk_info *ii)
return -1;
}
+ if (rst_freebind) {
+ int no = 0;
+
+ if (restore_opt(sk, SOL_IP, IP_FREEBIND, &no))
+ return -1;
+ }
+
return 0;
}
--
2.4.3
More information about the CRIU
mailing list