From 6c60b675880a49554b4d2fac50e4d823ca46a558 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 7 May 2021 15:11:14 +0200 Subject: [PATCH] plugins: netlink: fix resync request size alignment with kernel For RTM_GETLINK we need a `struct ifinfomsg`, not `struct rtmsg`, otherwise the kernel will get 8 extra bytes and complain about it. This patch makes sure to set the correct iface change mask as well, and increases the debug logs a bit to get a fix on sizes used. We increase the recv() buffer 8k -> 64k to make sure we can get all data in one big swoop. Plan is to refactor this mess in a later commit. Signed-off-by: Joachim Wiberg --- plugins/netlink.c | 53 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/plugins/netlink.c b/plugins/netlink.c index 28e47d9c..1693b6c7 100644 --- a/plugins/netlink.c +++ b/plugins/netlink.c @@ -32,7 +32,16 @@ #include "plugin.h" #include "service.h" -#define NL_BUFSZ 8192 +/* Used on resync, when we potentially read ALL interfaces in the system */ +#define NL_BUFSZ 65536 + +struct nl_request { + struct nlmsghdr nh; + union { + struct rtmsg rtm; + struct ifinfomsg ifi; + }; +}; static int nl_defidx; static int nl_ifdown; @@ -262,19 +271,42 @@ static int nl_parse(struct nlmsghdr *nh, ssize_t len) static int nl_resync_act(int sd, unsigned int seq, int type) { - struct nlmsghdr *nh; + struct nl_request *nlr = (struct nl_request *)nl_buf; + ssize_t len; - nh = (struct nlmsghdr *)nl_buf; - nh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - nh->nlmsg_type = type; - nh->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; - nh->nlmsg_seq = seq; - nh->nlmsg_pid = 1; + memset(nlr, 0, sizeof(struct nl_request)); + nlr->nh.nlmsg_type = type; + nlr->nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + nlr->nh.nlmsg_seq = seq; + nlr->nh.nlmsg_pid = 1; - if (send(sd, nh, nh->nlmsg_len, 0) < 0) + switch (type) { + case RTM_GETROUTE: + nlr->rtm.rtm_family = AF_INET; + nlr->rtm.rtm_table = RT_TABLE_MAIN; + nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + break; + + case RTM_GETLINK: + nlr->ifi.ifi_family = AF_UNSPEC; + nlr->ifi.ifi_change = 0xFFFFFFFF; + nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + break; + + default: + _w("Cannot resync, unhandled message type %d", type); + return -1; + } + + if (send(sd, nlr, nlr->nh.nlmsg_len, 0) < 0) return 1; - return nl_parse(nh, recv(sd, nl_buf, NL_BUFSZ, 0)); + len = recv(sd, nl_buf, NL_BUFSZ, 0); + if (len < 0) + return -1; + + _d("recv %lld bytes in resync path", len); + return nl_parse((struct nlmsghdr *)nl_buf, len); } static void nl_resync_routes(int sd, unsigned int seq) @@ -340,6 +372,7 @@ static void nl_callback(void *arg, int sd, int events) return; } + _d("recv %lld bytes in regular path", len); nl_parse((struct nlmsghdr *)nl_buf, len); /*