From: Andrei Vagin <ava...@virtuozzo.com>

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

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

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;
 }
-- 
1.8.3.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to