Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sk-inet: Add support for checkpoint/restore of ICMP sockets #2558

Open
wants to merge 8 commits into
base: criu-dev
Choose a base branch
from
7 changes: 5 additions & 2 deletions criu/sk-inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ static int can_dump_ipproto(unsigned int ino, int proto, int type)
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_UDPLITE:
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
break;
default:
pr_err("Unsupported proto %d for socket %x\n", proto, ino);
Expand Down Expand Up @@ -915,8 +917,9 @@ static int open_inet_sk(struct file_desc *d, int *new_fd)
}

if (ie->src_port) {
if (inet_bind(sk, ii))
goto err;
if (ie->proto != IPPROTO_ICMP && ie->proto != IPPROTO_ICMPV6)
if (inet_bind(sk, ii))
goto err;
}

/*
Expand Down
32 changes: 31 additions & 1 deletion criu/sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ enum socket_cl_bits {
INET_UDP_CL_BIT,
INET_UDPLITE_CL_BIT,
INET_RAW_CL_BIT,
INET_ICMP_CL_BIT,
INET6_TCP_CL_BIT,
INET6_UDP_CL_BIT,
INET6_UDPLITE_CL_BIT,
INET6_RAW_CL_BIT,
INET6_ICMP_CL_BIT,
UNIX_CL_BIT,
PACKET_CL_BIT,
_MAX_CL_BIT,
Expand All @@ -161,6 +163,8 @@ static inline enum socket_cl_bits get_collect_bit_nr(unsigned int family, unsign
return INET_UDPLITE_CL_BIT;
if (proto == IPPROTO_RAW)
return INET_RAW_CL_BIT;
if (proto == IPPROTO_ICMP)
return INET_ICMP_CL_BIT;
}
if (family == AF_INET6) {
if (proto == IPPROTO_TCP)
Expand All @@ -171,6 +175,8 @@ static inline enum socket_cl_bits get_collect_bit_nr(unsigned int family, unsign
return INET6_UDPLITE_CL_BIT;
if (proto == IPPROTO_RAW)
return INET6_RAW_CL_BIT;
if (proto == IPPROTO_ICMPV6)
return INET6_ICMP_CL_BIT;
}

pr_err("Unknown pair family %d proto %d\n", family, proto);
Expand Down Expand Up @@ -282,6 +288,12 @@ void preload_socket_modules(void)
req.r.i.sdiag_protocol = IPPROTO_RAW;
probe_diag(nl, &req, -ENOENT);

req.r.i.sdiag_protocol = IPPROTO_ICMP;
probe_diag(nl, &req, -ENOENT);

req.r.i.sdiag_protocol = IPPROTO_ICMPV6;
probe_diag(nl, &req, -ENOENT);

close(nl);
pr_info("Done probing\n");
}
Expand Down Expand Up @@ -773,6 +785,10 @@ static int inet_receive_one(struct nlmsghdr *h, struct ns_id *ns, void *arg)
case IPPROTO_RAW:
type = SOCK_RAW;
break;
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
type = SOCK_DGRAM;
break;
default:
BUG_ON(1);
return -1;
Expand All @@ -797,7 +813,7 @@ static int collect_err(int err, struct ns_id *ns, void *arg)
char family[32], proto[32];
char msg[256];

snprintf(msg, sizeof(msg), "Sockects collect procedure family %s proto %s",
snprintf(msg, sizeof(msg), "Sockets collect procedure family %s proto %s",
socket_family_name(gr->family, family, sizeof(family)),
socket_proto_name(gr->protocol, proto, sizeof(proto)));

Expand Down Expand Up @@ -905,6 +921,13 @@ int collect_sockets(struct ns_id *ns)
if (tmp)
err = tmp;

/* Collect IPv4 ICMP sockets */
req.r.i.sdiag_family = AF_INET;
req.r.i.sdiag_protocol = IPPROTO_ICMP;
req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */
set_collect_bit(req.r.n.sdiag_family, req.r.n.sdiag_protocol);
rst0git marked this conversation as resolved.
Show resolved Hide resolved

/* Collect IPv6 TCP sockets */
req.r.i.sdiag_family = AF_INET6;
req.r.i.sdiag_protocol = IPPROTO_TCP;
Expand Down Expand Up @@ -944,6 +967,13 @@ int collect_sockets(struct ns_id *ns)
if (tmp)
err = tmp;

/* Collect IPv6 ICMP sockets */
req.r.i.sdiag_family = AF_INET6;
req.r.i.sdiag_protocol = IPPROTO_ICMPV6;
req.r.i.idiag_ext = 0;
req.r.i.idiag_states = -1; /* All */
set_collect_bit(req.r.n.sdiag_family, req.r.n.sdiag_protocol);

req.r.p.sdiag_family = AF_PACKET;
req.r.p.sdiag_protocol = 0;
req.r.p.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST | PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG;
Expand Down
1 change: 1 addition & 0 deletions test/zdtm/static/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ TST_NOFILE := \
socket_udp-corked \
socket6_udp \
socket_udp_shutdown \
socket_icmp \
sk-freebind \
sk-freebind-false \
socket_udplite \
Expand Down
109 changes: 109 additions & 0 deletions test/zdtm/static/socket_icmp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "zdtmtst.h"

const char *test_doc = "static test for ICMP socket\n";
const char *test_author = "समीर सिंह Sameer Singh <lumarzeli30@gmail.com>\n";

/* Description:
* Send a ping to localhost using ICMP socket
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <netdb.h>

#define PACKET_SIZE 64

Check warning on line 20 in test/zdtm/static/socket_icmp.c

View workflow job for this annotation

GitHub Actions / build

#define RECV_TIMEOUT 1

int ping(void)
{
int ret, sock, seq = 0, recv_len = 0;
char packet[PACKET_SIZE], recv_packet[PACKET_SIZE];

struct timeval tv;
struct icmphdr icmp_header, *icmp_reply;
struct sockaddr_in addr, recv_addr;
socklen_t addr_len;

sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP);
if (sock < 0) {
pr_perror("Can't create socket");
return 1;
}


Check warning on line 39 in test/zdtm/static/socket_icmp.c

View workflow job for this annotation

GitHub Actions / build

tv.tv_sec = RECV_TIMEOUT;
tv.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
pr_perror("Can't set socket option");
return 1;
}

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");

for (;;) {
memset(&icmp_header, 0, sizeof(icmp_header));
icmp_header.type = ICMP_ECHO;
icmp_header.code = 0;
icmp_header.un.echo.id = getpid();
icmp_header.un.echo.sequence = seq++;

memcpy(packet, &icmp_header, sizeof(icmp_header));
memset(packet + sizeof(icmp_header), 0xa5,
PACKET_SIZE - sizeof(icmp_header));

Check warning on line 60 in test/zdtm/static/socket_icmp.c

View workflow job for this annotation

GitHub Actions / build


ret = sendto(sock, packet, PACKET_SIZE, 0,
(struct sockaddr *)&addr, sizeof(addr));

if (ret < 0) {
fail("Can't send");
return 1;
}

addr_len = sizeof(recv_addr);

ret = recvfrom(sock, recv_packet, sizeof(recv_packet), 0,
(struct sockaddr*)&recv_addr, &addr_len);

Check warning on line 73 in test/zdtm/static/socket_icmp.c

View workflow job for this annotation

GitHub Actions / build


if (ret < 0) {
fail("Can't recv");
return 1;
}

icmp_reply = (struct icmphdr *)recv_packet;

if (icmp_reply->type == ICMP_ECHOREPLY) {
printf("%d bytes from %s: icmp_seq=%d\n",
recv_len,

Check warning on line 84 in test/zdtm/static/socket_icmp.c

View workflow job for this annotation

GitHub Actions / build

inet_ntoa(recv_addr.sin_addr),
icmp_reply->un.echo.sequence);
}

sleep(1);
}

close(sock);
}

int main(int argc, char **argv)
{
int ret;
test_init(argc, argv);

test_daemon();
test_waitsig();
ss141309 marked this conversation as resolved.
Show resolved Hide resolved

ret = ping();
if (ret == 1)
fail("Cannot ping");

pass();
return 0;
}
Loading