nl80211: Implement netlink extended ACK support
Implement netlink extended ACK support to print out the error message (if any). Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
c481e1cbb7
commit
40432e6eb3
1 changed files with 56 additions and 1 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue