From 47ccf9a28bf201c84b55a74d090f1ffed5a66f30 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 13 Sep 2018 22:57:46 +0300 Subject: [PATCH] inet: raw -- Check for kernel diag module support To collect raw sockets we need the kernel to support raw_diag module. Signed-off-by: Cyrill Gorcunov Signed-off-by: Andrei Vagin --- criu/cr-check.c | 9 +++++++++ criu/sockets.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/criu/cr-check.c b/criu/cr-check.c index 3cdc45315..4bbe9e098 100644 --- a/criu/cr-check.c +++ b/criu/cr-check.c @@ -1086,6 +1086,13 @@ static int check_kcmp_epoll(void) return 0; } +static int check_net_diag_raw(void) +{ + check_sock_diag(); + return (socket_test_collect_bit(AF_INET, IPPROTO_RAW) && + socket_test_collect_bit(AF_INET6, IPPROTO_RAW)) ? 0 : -1; +} + static int (*chk_feature)(void); /* @@ -1194,6 +1201,7 @@ int cr_check(void) ret |= check_uffd_noncoop(); ret |= check_sk_netns(); ret |= check_kcmp_epoll(); + ret |= check_net_diag_raw(); } /* @@ -1292,6 +1300,7 @@ static struct feature_list feature_list[] = { { "can_map_vdso", check_can_map_vdso}, { "sk_ns", check_sk_netns }, { "sk_unix_file", check_sk_unix_file }, + { "net_diag_raw", check_net_diag_raw }, { "nsid", check_nsid }, { "link_nsid", check_link_nsid}, { "kcmp_epoll", check_kcmp_epoll}, diff --git a/criu/sockets.c b/criu/sockets.c index 9de00df63..14ba5f602 100644 --- a/criu/sockets.c +++ b/criu/sockets.c @@ -141,9 +141,11 @@ enum socket_cl_bits INET_TCP_CL_BIT, INET_UDP_CL_BIT, INET_UDPLITE_CL_BIT, + INET_RAW_CL_BIT, INET6_TCP_CL_BIT, INET6_UDP_CL_BIT, INET6_UDPLITE_CL_BIT, + INET6_RAW_CL_BIT, UNIX_CL_BIT, PACKET_CL_BIT, _MAX_CL_BIT, @@ -169,6 +171,8 @@ enum socket_cl_bits get_collect_bit_nr(unsigned int family, unsigned int proto) return INET_UDP_CL_BIT; if (proto == IPPROTO_UDPLITE) return INET_UDPLITE_CL_BIT; + if (proto == IPPROTO_RAW) + return INET_RAW_CL_BIT; } if (family == AF_INET6) { if (proto == IPPROTO_TCP) @@ -177,6 +181,8 @@ enum socket_cl_bits get_collect_bit_nr(unsigned int family, unsigned int proto) return INET6_UDP_CL_BIT; if (proto == IPPROTO_UDPLITE) return INET6_UDPLITE_CL_BIT; + if (proto == IPPROTO_RAW) + return INET6_RAW_CL_BIT; } pr_err("Unknown pair family %d proto %d\n", family, proto); @@ -686,6 +692,9 @@ static int inet_receive_one(struct nlmsghdr *h, struct ns_id *ns, void *arg) case IPPROTO_UDPLITE: type = SOCK_DGRAM; break; + case IPPROTO_RAW: + type = SOCK_RAW; + break; default: BUG_ON(1); return -1; @@ -761,6 +770,18 @@ int collect_sockets(struct ns_id *ns) if (tmp) err = tmp; + /* Collect IPv4 RAW sockets */ + req.r.i.sdiag_family = AF_INET; + req.r.i.sdiag_protocol = IPPROTO_RAW; + req.r.i.idiag_ext = 0; + req.r.i.idiag_states = -1; /* All */ + tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); + if (tmp) { + pr_warn("The current kernel doesn't support ipv4 raw_diag module\n"); + if (tmp != -ENOENT) + err = tmp; + } + /* Collect IPv6 TCP sockets */ req.r.i.sdiag_family = AF_INET6; req.r.i.sdiag_protocol = IPPROTO_TCP; @@ -792,6 +813,18 @@ int collect_sockets(struct ns_id *ns) if (tmp) err = tmp; + /* Collect IPv6 RAW sockets */ + req.r.i.sdiag_family = AF_INET6; + req.r.i.sdiag_protocol = IPPROTO_RAW; + req.r.i.idiag_ext = 0; + req.r.i.idiag_states = -1; /* All */ + tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, ns, &req.r.i); + if (tmp) { + pr_warn("The current kernel doesn't support ipv6 raw_diag module\n"); + if (tmp != -ENOENT) + err = tmp; + } + req.r.p.sdiag_family = AF_PACKET; req.r.p.sdiag_protocol = 0; req.r.p.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST |