[CRIU] [PATCH 1/3] net: dump netfilter conntracks and expectations

Andrey Vagin avagin at openvz.org
Thu Feb 4 11:36:14 PST 2016


From: Andrew Vagin <avagin at virtuozzo.com>

We request all contracks via netlink and save netlink messages which
describe them in an image file, then we send these netlink messages back on restore.

https://github.com/xemul/criu/issues/54
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 image-desc.c         |   2 +
 include/image-desc.h |   2 +
 include/magic.h      |   2 +
 net.c                | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 132 insertions(+)

diff --git a/image-desc.c b/image-desc.c
index 9fb96c8..6770675 100644
--- a/image-desc.c
+++ b/image-desc.c
@@ -95,6 +95,8 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
 	FD_ENTRY(CPUINFO,	"cpuinfo"),
 	FD_ENTRY(SECCOMP,	"seccomp"),
 	FD_ENTRY(USERNS,	"userns-%d"),
+	FD_ENTRY(NETNF_CT,	"netns-ct-%d"),
+	FD_ENTRY(NETNF_EXP,	"netns-exp-%d"),
 
 	[CR_FD_STATS] = {
 		.fmt	= "stats-%s",
diff --git a/include/image-desc.h b/include/image-desc.h
index 90933e9..532ced8 100644
--- a/include/image-desc.h
+++ b/include/image-desc.h
@@ -44,6 +44,8 @@ enum {
 	CR_FD_IPTABLES,
 	CR_FD_IP6TABLES,
 	CR_FD_NETNS,
+	CR_FD_NETNF_CT,
+	CR_FD_NETNF_EXP,
 	_CR_FD_NETNS_TO,
 
 	CR_FD_PSTREE,
diff --git a/include/magic.h b/include/magic.h
index 3cb3766..b11a70e 100644
--- a/include/magic.h
+++ b/include/magic.h
@@ -100,6 +100,8 @@
 #define TMPFS_DEV_MAGIC		RAW_IMAGE_MAGIC
 #define IPTABLES_MAGIC		RAW_IMAGE_MAGIC
 #define IP6TABLES_MAGIC		RAW_IMAGE_MAGIC
+#define NETNF_CT_MAGIC		RAW_IMAGE_MAGIC
+#define NETNF_EXP_MAGIC		RAW_IMAGE_MAGIC
 
 #define PAGES_OLD_MAGIC		PAGEMAP_MAGIC
 #define SHM_PAGES_OLD_MAGIC	PAGEMAP_MAGIC
diff --git a/net.c b/net.c
index 51b3159..c611f61 100644
--- a/net.c
+++ b/net.c
@@ -2,6 +2,9 @@
 #include <sys/socket.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+#include <linux/netfilter/nf_conntrack_tcp.h>
 #include <string.h>
 #include <net/if_arp.h>
 #include <sys/wait.h>
@@ -344,6 +347,121 @@ unk:
 	return ret;
 }
 
+static int dump_one_nf(struct nlmsghdr *hdr, void *arg)
+{
+	struct cr_img *img = arg;
+
+	if (lazy_image(img) && open_image_lazy(img))
+		return -1;
+
+	if (write_img_buf(img, hdr, hdr->nlmsg_len))
+		return -1;
+
+	return 0;
+}
+
+static int restore_nf_ct(int pid, int type)
+{
+	struct nlmsghdr *nlh = NULL;
+	int exit_code = -1, sk;
+	struct cr_img *img;
+
+	img = open_image(type, O_RSTR, pid);
+	if (empty_image(img)) {
+		close_image(img);
+		return 0;
+	}
+
+	sk = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+	if (sk < 0) {
+		pr_perror("Can't open rtnl sock for net dump");
+		goto out_img;
+	}
+
+	nlh = xmalloc(sizeof(struct nlmsghdr));
+	if (nlh == NULL)
+		goto out;
+
+	while (1) {
+		struct nlmsghdr *p;
+		int ret;
+
+		ret = read_img_buf_eof(img, nlh, sizeof(struct nlmsghdr));
+		if (ret < 0)
+			goto out;
+		if (ret == 0)
+			break;
+
+		p = xrealloc(nlh, nlh->nlmsg_len);
+		if (p == NULL)
+			goto out;
+		nlh = p;
+
+		ret = read_img_buf_eof(img, nlh + 1, nlh->nlmsg_len - sizeof(struct nlmsghdr));
+		if (ret < 0)
+			goto out;
+		if (ret == 0) {
+			pr_err("The image file was truncated\n");
+			goto out;
+		}
+
+		nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE;
+		ret = do_rtnl_req(sk, nlh, nlh->nlmsg_len, NULL, NULL, NULL);
+		if (ret)
+			goto out;
+	}
+
+	exit_code = 0;
+out:
+	xfree(nlh);
+	close(sk);
+out_img:
+	close_image(img);
+	return exit_code;
+}
+
+static int dump_nf_ct(struct cr_imgset *fds, int type)
+{
+	struct cr_img *img;
+	struct {
+		struct nlmsghdr nlh;
+		struct nfgenmsg g;
+	} req;
+	int sk, ret;
+
+	pr_info("Dumping netns links\n");
+
+	ret = sk = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+	if (sk < 0) {
+		pr_perror("Can't open rtnl sock for net dump");
+		goto out;
+	}
+
+	memset(&req, 0, sizeof(req));
+	req.nlh.nlmsg_len = sizeof(req);
+	req.nlh.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8);
+
+	if (type == CR_FD_NETNF_CT)
+		req.nlh.nlmsg_type |= IPCTNL_MSG_CT_GET;
+	else if (type == CR_FD_NETNF_EXP)
+		req.nlh.nlmsg_type |= IPCTNL_MSG_EXP_GET;
+	else
+		BUG();
+
+	req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+	req.nlh.nlmsg_pid = 0;
+	req.nlh.nlmsg_seq = CR_NLMSG_SEQ;
+	req.g.nfgen_family = AF_UNSPEC;
+
+	img = img_from_set(fds, type);
+
+	ret = do_rtnl_req(sk, &req, sizeof(req), dump_one_nf, NULL, img);
+	close(sk);
+out:
+	return ret;
+
+}
+
 static int dump_links(struct cr_imgset *fds)
 {
 	int sk, ret;
@@ -904,6 +1022,10 @@ int dump_net_ns(int ns_id)
 		ret = dump_rule(fds);
 	if (!ret)
 		ret = dump_iptables(fds);
+	if (!ret)
+		ret = dump_nf_ct(fds, CR_FD_NETNF_CT);
+	if (!ret)
+		ret = dump_nf_ct(fds, CR_FD_NETNF_EXP);
 
 	close(ns_sysfs_fd);
 	ns_sysfs_fd = -1;
@@ -931,6 +1053,10 @@ int prepare_net_ns(int pid)
 		ret = restore_rule(pid);
 	if (!ret)
 		ret = restore_iptables(pid);
+	if (!ret)
+		ret = restore_nf_ct(pid, CR_FD_NETNF_CT);
+	if (!ret)
+		ret = restore_nf_ct(pid, CR_FD_NETNF_EXP);
 
 	close_service_fd(NS_FD_OFF);
 
-- 
2.4.3



More information about the CRIU mailing list