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

kerndat: Make socket feature probing work on IPv6-only host.

Try IPv6 if IPv4 sockets are not supported.

Signed-off-by: Michał Mirosław <emmir@google.com>
This commit is contained in:
Michał Mirosław
2023-06-21 18:54:28 +02:00
committed by Andrei Vagin
parent eea0d6edee
commit e5c9bc4d08
2 changed files with 42 additions and 15 deletions

View File

@@ -1086,6 +1086,8 @@ static int kerndat_tcp_repair_window(void)
int sk, val = 1; int sk, val = 1;
sk = socket(AF_INET, SOCK_STREAM, 0); sk = socket(AF_INET, SOCK_STREAM, 0);
if (sk < 0 && errno == EAFNOSUPPORT)
sk = socket(AF_INET6, SOCK_STREAM, 0);
if (sk < 0) { if (sk < 0) {
pr_perror("Unable to create inet socket"); pr_perror("Unable to create inet socket");
goto errn; goto errn;

View File

@@ -12,7 +12,7 @@
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <stdint.h> #include <stdint.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */ #include <netinet/in.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <sched.h> #include <sched.h>
@@ -615,29 +615,52 @@ static int kerndat_iptables_has_xtlocks(void)
return 0; return 0;
} }
int kerndat_tcp_repair(void) /*
{ * Unfortunately in C htonl() is not constexpr and cannot be used in a static
int sock, clnt = -1, yes = 1, exit_code = -1; * initialization below.
struct sockaddr_in addr; */
socklen_t aux; #define constant_htonl(x) \
(__BYTE_ORDER == __BIG_ENDIAN ? (x) : \
(((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
memset(&addr, 0, sizeof(addr)); static int kerndat_tcp_repair(void)
addr.sin_family = AF_INET; {
inet_pton(AF_INET, "127.0.0.1", &(addr.sin_addr)); static const struct sockaddr_in loopback_ip4 = {
addr.sin_port = 0; .sin_family = AF_INET,
.sin_port = 0,
.sin_addr = { constant_htonl(INADDR_LOOPBACK) },
};
static const struct sockaddr_in6 loopback_ip6 = {
.sin6_family = AF_INET6,
.sin6_port = 0,
.sin6_addr = IN6ADDR_LOOPBACK_INIT,
};
int sock, clnt = -1, yes = 1, exit_code = -1;
const struct sockaddr *addr;
struct sockaddr_storage listener_addr;
socklen_t addrlen;
addr = (const struct sockaddr *)&loopback_ip4;
addrlen = sizeof(loopback_ip4);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0 && errno == EAFNOSUPPORT) {
addr = (const struct sockaddr *)&loopback_ip6;
addrlen = sizeof(loopback_ip6);
sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
}
if (sock < 0) { if (sock < 0) {
pr_perror("Unable to create a socket"); pr_perror("Unable to create a socket");
return -1; return -1;
} }
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) { if (bind(sock, addr, addrlen)) {
pr_perror("Unable to bind a socket"); pr_perror("Unable to bind a socket");
goto err; goto err;
} }
aux = sizeof(addr); addrlen = sizeof(listener_addr);
if (getsockname(sock, (struct sockaddr *)&addr, &aux)) { if (getsockname(sock, (struct sockaddr *)&listener_addr, &addrlen)) {
pr_perror("Unable to get a socket name"); pr_perror("Unable to get a socket name");
goto err; goto err;
} }
@@ -647,13 +670,13 @@ int kerndat_tcp_repair(void)
goto err; goto err;
} }
clnt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); clnt = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (clnt < 0) { if (clnt < 0) {
pr_perror("Unable to create a socket"); pr_perror("Unable to create a socket");
goto err; goto err;
} }
if (connect(clnt, (struct sockaddr *)&addr, sizeof(addr))) { if (connect(clnt, (const struct sockaddr *)&listener_addr, addrlen)) {
pr_perror("Unable to connect a socket"); pr_perror("Unable to connect a socket");
goto err; goto err;
} }
@@ -977,6 +1000,8 @@ int kerndat_sockopt_buf_lock(void)
int sock; int sock;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0 && errno == EAFNOSUPPORT)
sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) { if (sock < 0) {
pr_perror("Unable to create a socket"); pr_perror("Unable to create a socket");
return -1; return -1;