[CRIU] [PATCH 2/2] inet: set IP_FREEBIND before binding socket to an ipv6 address (v2)
Andrey Vagin
avagin at openvz.org
Thu Nov 19 06:48:22 PST 2015
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;
+ }
+
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;
}
--
2.4.3
More information about the CRIU
mailing list