[CRIU] [PATCH 7/8] sockets: restore netlink sockets

Andrey Vagin avagin at openvz.org
Mon Mar 25 11:28:48 EDT 2013


Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c      |  3 ++
 include/sockets.h |  2 ++
 sk-netlink.c      | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 93 insertions(+)

diff --git a/cr-restore.c b/cr-restore.c
index b4a6da2..4d99a9a 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -133,6 +133,9 @@ static int root_prepare_shared(void)
 	if (collect_packet_sockets())
 		return -1;
 
+	if (collect_netlink_sockets())
+		return -1;
+
 	if (collect_eventfd())
 		return -1;
 
diff --git a/include/sockets.h b/include/sockets.h
index 02b0584..a596fa8 100644
--- a/include/sockets.h
+++ b/include/sockets.h
@@ -39,6 +39,8 @@ extern int collect_unix_sockets(void);
 extern int fix_external_unix_sockets(void);
 extern int resolve_unix_peers(void);
 
+extern int collect_netlink_sockets(void);
+
 extern void show_unixsk(int fd, struct cr_options *o);
 extern void show_inetsk(int fd, struct cr_options *o);
 extern void show_sk_queues(int fd, struct cr_options *o);
diff --git a/sk-netlink.c b/sk-netlink.c
index e387cc1..f601b71 100644
--- a/sk-netlink.c
+++ b/sk-netlink.c
@@ -162,3 +162,91 @@ int dump_one_netlink(struct fd_parms *p, int lfd, const int fdinfo)
 {
 	return do_dump_gen_file(p, lfd, &netlink_dump_ops, fdinfo);
 }
+
+struct netlink_sock_info {
+	NetlinkSkEntry *nse;
+	struct file_desc d;
+};
+
+static int open_netlink_sk(struct file_desc *d)
+{
+	struct netlink_sock_info *nsi;
+	NetlinkSkEntry *nse;
+	struct sockaddr_nl addr;
+	int sk = -1;
+
+	nsi = container_of(d, struct netlink_sock_info, d);
+	nse = nsi->nse;
+
+	pr_info("Opening netlink socket id %#x\n", nse->id);
+
+	sk = socket(PF_NETLINK, SOCK_RAW, nse->protocol);
+	if (sk < 0) {
+		pr_perror("Can't create netlink sock");
+		goto err;
+	}
+
+	if (nse->portid) {
+		memset(&addr, 0, sizeof(addr));
+		addr.nl_family = AF_NETLINK;
+		if (nse->n_groups > 1) {
+			pr_err("Groups above 32 are not supported yet\n");
+			goto err;
+		}
+		if (nse->n_groups)
+			addr.nl_groups = nse->groups[0];
+		addr.nl_pid = nse->portid;
+
+		if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+			pr_perror("Can't bind netlink socket");
+			goto err;
+		}
+	}
+
+	if (nse->state == NETLINK_CONNECTED) {
+		addr.nl_family = AF_NETLINK;
+		addr.nl_groups = 1 << (nse->dst_group - 1);
+		addr.nl_pid = nse->dst_portid;
+		if (connect(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+			pr_perror("Can't connect netlink socket");
+			goto err;
+		}
+	}
+
+	if (rst_file_params(sk, nse->fown, nse->flags))
+		goto err;
+
+	if (restore_socket_opts(sk, nse->opts))
+		goto err;
+
+	return sk;
+err:
+	close(sk);
+	return -1;
+}
+
+static struct file_desc_ops netlink_sock_desc_ops = {
+	.type = FD_TYPES__NETLINKSK,
+	.open = open_netlink_sk,
+};
+
+static int collect_one_netlink_sk(void *o, ProtobufCMessage *base)
+{
+	struct netlink_sock_info *si = o;
+
+	si->nse = pb_msg(base, NetlinkSkEntry);
+	file_desc_add(&si->d, si->nse->id, &netlink_sock_desc_ops);
+
+	return 0;
+}
+
+int collect_netlink_sockets(void)
+{
+	int ret = collect_image(CR_FD_NETLINKSK, PB_NETLINKSK,
+			sizeof(struct netlink_sock_info), collect_one_netlink_sk);
+
+	if (ret < 0 && errno == ENOENT)
+		return 0;
+
+	return ret;
+}
-- 
1.7.11.7



More information about the CRIU mailing list