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