From 40432e6eb37d62dabbf4416f3062cdf2a2fa1b40 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Oct 2018 15:55:49 +0200 Subject: [PATCH] nl80211: Implement netlink extended ACK support Implement netlink extended ACK support to print out the error message (if any). Signed-off-by: Johannes Berg --- src/drivers/driver_nl80211.c | 57 +++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 39a02d3ee..b26894f83 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -40,6 +40,29 @@ #include "driver_nl80211.h" +/* support for extack if compilation headers are too old */ +#ifndef NETLINK_EXT_ACK +#define NETLINK_EXT_ACK 11 +enum nlmsgerr_attrs { + NLMSGERR_ATTR_UNUSED, + NLMSGERR_ATTR_MSG, + NLMSGERR_ATTR_OFFS, + NLMSGERR_ATTR_COOKIE, + + __NLMSGERR_ATTR_MAX, + NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 +}; +#endif +#ifndef NLM_F_CAPPED +#define NLM_F_CAPPED 0x100 +#endif +#ifndef NLM_F_ACK_TLVS +#define NLM_F_ACK_TLVS 0x200 +#endif +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + #ifndef CONFIG_LIBNL20 /* * libnl 1.1 has a bug, it tries to allocate socket numbers densely @@ -302,8 +325,35 @@ static int finish_handler(struct nl_msg *msg, void *arg) static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { + struct nlmsghdr *nlh = (struct nlmsghdr *) err - 1; + int len = nlh->nlmsg_len; + struct nlattr *attrs; + struct nlattr *tb[NLMSGERR_ATTR_MAX + 1]; int *ret = arg; + int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh); + *ret = err->error; + + if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) + return NL_SKIP; + + if (!(nlh->nlmsg_flags & NLM_F_CAPPED)) + ack_len += err->msg.nlmsg_len - sizeof(*nlh); + + if (len <= ack_len) + return NL_STOP; + + attrs = (void *) ((unsigned char *) nlh + ack_len); + len -= ack_len; + + nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, len, NULL); + if (tb[NLMSGERR_ATTR_MSG]) { + len = strnlen((char *) nla_data(tb[NLMSGERR_ATTR_MSG]), + nla_len(tb[NLMSGERR_ATTR_MSG])); + wpa_printf(MSG_ERROR, "nl80211: kernel reports: %*s", + len, (char *) nla_data(tb[NLMSGERR_ATTR_MSG])); + } + return NL_SKIP; } @@ -342,7 +392,7 @@ static int send_and_recv(struct nl80211_global *global, void *valid_data) { struct nl_cb *cb; - int err = -ENOMEM; + int err = -ENOMEM, opt; if (!msg) return -ENOMEM; @@ -351,6 +401,11 @@ static int send_and_recv(struct nl80211_global *global, if (!cb) goto out; + /* try to set NETLINK_EXT_ACK to 1, ignoring errors */ + opt = 1; + setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK, + NETLINK_EXT_ACK, &opt, sizeof(opt)); + err = nl_send_auto_complete(nl_handle, msg); if (err < 0) goto out;