summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2018-03-08 17:01:35 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2018-03-08 17:49:18 +0100
commit5e27a30e1d7b64f056d666463aa6c6894531462d (patch)
tree530ce6634fd7545b7bf2ebe15889f305e6a246c1
parent39fde61a5a160ac8be644290226d3cff94c4b342 (diff)
downloadNetworkManager-bg/extack.tar.gz
platform: print error message from netlink extended ackbg/extack
From v4.12 the kernel appends some attributes to netlink acks containing a textual description of the error and other fields (see commit [1]). Parse those attributes and print the error message. Example: platform-linux: netlink: recvmsg: error message from kernel: Network is unreachable (101) "Nexthop has invalid gateway" for request 12 [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2d4bc93368f5a0ddb57c8c885cdad9c9b7a10ed5
-rw-r--r--src/platform/nm-linux-platform.c26
-rw-r--r--src/platform/nm-netlink.c20
-rw-r--r--src/platform/nm-netlink.h13
3 files changed, 57 insertions, 2 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index dd5a52d265..74f55b5922 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -6596,11 +6596,31 @@ continue_reading:
abort_parsing = TRUE;
} else if (e->error) {
int errsv = e->error > 0 ? e->error : -e->error;
+ const char *extack_msg = NULL;
+
+ if (hdr->nlmsg_flags & NLM_F_ACK_TLVS) {
+ static const struct nla_policy policy[NLMSGERR_ATTR_MAX + 1] = {
+ [NLMSGERR_ATTR_MSG] = { .type = NLA_STRING },
+ [NLMSGERR_ATTR_OFFS] = { .type = NLA_U32 },
+ };
+ struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
+ struct nlattr *tlvs;
+
+ nm_assert (hdr->nlmsg_len >= sizeof (*e) + e->msg.nlmsg_len);
+
+ tlvs = (struct nlattr *) ((char *) e + sizeof (*e) + e->msg.nlmsg_len - NLMSG_HDRLEN);
+ if (!nla_parse (tb, NLMSGERR_ATTR_MAX, tlvs,
+ hdr->nlmsg_len - sizeof (*e) - e->msg.nlmsg_len, policy)) {
+ if (tb[NLMSGERR_ATTR_MSG])
+ extack_msg = nla_get_string (tb[NLMSGERR_ATTR_MSG]);
+ }
+ }
/* Error message reported back from kernel. */
- _LOGD ("netlink: recvmsg: error message from kernel: %s (%d) for request %d",
+ _LOGE ("netlink: recvmsg: error message from kernel: %s (%d)%s%s%s for request %d",
strerror (errsv),
errsv,
+ NM_PRINT_FMT_QUOTED (extack_msg, " \"", extack_msg, "\"", ""),
nlmsg_hdr (msg)->nlmsg_seq);
seq_result = -errsv;
} else
@@ -6948,6 +6968,10 @@ constructed (GObject *_object)
nle = nl_socket_set_buffer_size (priv->nlh, 8*1024*1024, 0);
g_assert (!nle);
+ nle = nl_socket_set_ext_ack (priv->nlh, TRUE);
+ if (nle)
+ _LOGD ("could not enable extended acks on netlink socket");
+
/* explicitly set the msg buffer size and disable MSG_PEEK.
* If we later encounter NLE_MSG_TRUNC, we will adjust the buffer size. */
nl_socket_disable_msg_peek (priv->nlh);
diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c
index 7d794f7737..0baaaf0b47 100644
--- a/src/platform/nm-netlink.c
+++ b/src/platform/nm-netlink.c
@@ -38,6 +38,10 @@
#define NL_MSG_PEEK_EXPLICIT (1<<4)
#define NL_NO_AUTO_ACK (1<<5)
+#ifndef NETLINK_EXT_ACK
+#define NETLINK_EXT_ACK 11
+#endif
+
#define NL_MSG_CRED_PRESENT 1
struct nl_msg {
@@ -933,6 +937,22 @@ nl_socket_add_memberships (struct nl_sock *sk, int group, ...)
return 0;
}
+int
+nl_socket_set_ext_ack (struct nl_sock *sk, gboolean enable)
+{
+ int err;
+
+ if (sk->s_fd == -1)
+ return -NLE_BAD_SOCK;
+
+ enable = !!enable;
+ err = setsockopt (sk->s_fd, SOL_NETLINK, NETLINK_EXT_ACK, &enable, sizeof (enable));
+ if (err < 0)
+ return -nl_syserr2nlerr (errno);
+
+ return 0;
+}
+
void nl_socket_disable_msg_peek (struct nl_sock *sk)
{
sk->s_flags |= NL_MSG_PEEK_EXPLICIT;
diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h
index 42e46d6c69..bd8a9cfaf0 100644
--- a/src/platform/nm-netlink.h
+++ b/src/platform/nm-netlink.h
@@ -26,7 +26,6 @@
#include <linux/genetlink.h>
/*****************************************************************************/
-
#define _NLE_BASE 100000
#define NLE_UNSPEC (_NLE_BASE + 0)
#define NLE_BUG (_NLE_BASE + 1)
@@ -42,6 +41,16 @@
#define _NLE_BASE_END (_NLE_BASE + 11)
+#define NLMSGERR_ATTR_UNUSED 0
+#define NLMSGERR_ATTR_MSG 1
+#define NLMSGERR_ATTR_OFFS 2
+#define NLMSGERR_ATTR_COOKIE 3
+#define NLMSGERR_ATTR_MAX 3
+
+#ifndef NLM_F_ACK_TLVS
+#define NLM_F_ACK_TLVS 0x200
+#endif
+
static inline int
nl_errno (int err)
{
@@ -484,6 +493,8 @@ int nl_recvmsgs (struct nl_sock *sk, const struct nl_cb *cb);
int nl_wait_for_ack (struct nl_sock *sk,
const struct nl_cb *cb);
+int nl_socket_set_ext_ack (struct nl_sock *sk, gboolean enable);
+
/*****************************************************************************/
#endif /* __NM_NETLINK_H__ */