[Devel,2/5] netlink: dump/restore netlink options

Submitted by Andrei Vagin on Feb. 19, 2017, 6:58 a.m.

Details

Message ID 1487487496-12063-3-git-send-email-avagin@openvz.org
State New
Series "A few fixes for netlink sockets"
Headers show

Commit Message

Andrei Vagin Feb. 19, 2017, 6:58 a.m.
From: Andrei Vagin <avagin@virtuozzo.com>

There are a few netlink specific opotions, which have to be dumped.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/sk-netlink.c       | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
 images/sk-netlink.proto |  9 ++++++++
 2 files changed, 69 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/sk-netlink.c b/criu/sk-netlink.c
index 3966f82..71bb77e 100644
--- a/criu/sk-netlink.c
+++ b/criu/sk-netlink.c
@@ -1,5 +1,6 @@ 
 #include <unistd.h>
 #include <linux/netlink.h>
+#include <linux/socket.h>
 #include <linux/rtnetlink.h>
 #include <libnl3/netlink/msg.h>
 
@@ -15,6 +16,10 @@ 
 #include "sk-queue.h"
 #include "kerndat.h"
 
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
 struct netlink_sk_desc {
 	struct socket_desc	sd;
 	u32                     portid;
@@ -117,11 +122,41 @@  static bool can_dump_netlink_sk(int lfd, struct netlink_sk_desc *sk)
 	return true;
 }
 
+static int dump_nl_opts(int sk, NlSkOptsEntry *e)
+{
+	int ret = 0;
+	socklen_t len;
+
+	ret |= dump_opt(sk, SOL_NETLINK, NETLINK_PKTINFO, &e->pktinfo);
+	ret |= dump_opt(sk, SOL_NETLINK, NETLINK_BROADCAST_ERROR, &e->broadcast_error);
+	ret |= dump_opt(sk, SOL_NETLINK, NETLINK_NO_ENOBUFS, &e->no_enobufs);
+
+	len = sizeof(e->listen_all_nsid);
+	if (getsockopt(sk, SOL_NETLINK, NETLINK_LISTEN_ALL_NSID, &e->listen_all_nsid, &len)) {
+		if (errno == ENOPROTOOPT) {
+			pr_warn("Unable to get NETLINK_LISTEN_ALL_NSID");
+		} else {
+			pr_perror("Can't get NETLINK_LISTEN_ALL_NSID opt");
+			ret = -1;
+		}
+	}
+
+	len = sizeof(e->cap_ack);
+	if (getsockopt(sk, SOL_NETLINK, NETLINK_CAP_ACK, &e->cap_ack, &len) &&
+	    errno != ENOPROTOOPT) {
+		pr_perror("Can't get NETLINK_CAP_ACK opt");
+		ret = -1;
+	}
+
+	return ret;
+}
+
 static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p)
 {
 	struct netlink_sk_desc *sk;
 	NetlinkSkEntry ne = NETLINK_SK_ENTRY__INIT;
 	SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
+	NlSkOptsEntry nlopts = NL_SK_OPTS_ENTRY__INIT;
 
 	sk = (struct netlink_sk_desc *)lookup_socket(p->stat.st_ino, PF_NETLINK, 0);
 	if (IS_ERR(sk))
@@ -174,6 +209,10 @@  static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p)
 
 	ne.fown = (FownEntry *)&p->fown;
 	ne.opts	= &skopts;
+	ne.nl_opts = &nlopts;
+
+	if (dump_nl_opts(lfd, &nlopts))
+		goto err;
 
 	if (dump_socket_opts(lfd, &skopts))
 		goto err;
@@ -222,6 +261,24 @@  static int restore_netlink_queue(int sk, int id)
 	return 0;
 }
 
+static int restore_nl_opts(int sk, NlSkOptsEntry *e)
+{
+	int yes = 1, ret = 0;
+
+	if (e->pktinfo)
+		ret |= restore_opt(sk, SOL_NETLINK, NETLINK_PKTINFO, &yes);
+	if (e->broadcast_error)
+		ret |= restore_opt(sk, SOL_NETLINK, NETLINK_BROADCAST_ERROR, &yes);
+	if (e->no_enobufs)
+		ret |= restore_opt(sk, SOL_NETLINK, NETLINK_NO_ENOBUFS, &yes);
+	if (e->listen_all_nsid)
+		ret |= restore_opt(sk, SOL_NETLINK, NETLINK_LISTEN_ALL_NSID, &yes);
+	if (e->cap_ack)
+		ret |= restore_opt(sk, SOL_NETLINK, NETLINK_CAP_ACK, &yes);
+
+	return ret;
+}
+
 static int open_netlink_sk(struct file_desc *d, int *new_fd)
 {
 	struct netlink_sock_info *nsi;
@@ -273,6 +330,9 @@  static int open_netlink_sk(struct file_desc *d, int *new_fd)
 	if (restore_netlink_queue(sk, nse->id))
 		goto err;
 
+	if (nse->nl_opts && restore_nl_opts(sk, nse->nl_opts))
+		goto err;
+
 	if (restore_socket_opts(sk, nse->opts))
 		goto err;
 
diff --git a/images/sk-netlink.proto b/images/sk-netlink.proto
index ed24c50..dd3be4c 100644
--- a/images/sk-netlink.proto
+++ b/images/sk-netlink.proto
@@ -4,6 +4,14 @@  import "opts.proto";
 import "fown.proto";
 import "sk-opts.proto";
 
+message nl_sk_opts_entry {
+	required bool			pktinfo		= 1;
+	required bool			broadcast_error = 2;
+	required bool			no_enobufs	= 3;
+	required bool			listen_all_nsid	= 4;
+	required bool			cap_ack		= 5;
+}
+
 message netlink_sk_entry {
 	required uint32			id		=  1;
 	required uint32			ino		=  2;
@@ -16,4 +24,5 @@  message netlink_sk_entry {
 	required uint32			dst_group	=  10;
 	required fown_entry		fown		=  11;
 	required sk_opts_entry		opts		=  12;
+	optional nl_sk_opts_entry	nl_opts		=  14;
 }