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"
|
#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
|
#ifndef CONFIG_LIBNL20
|
||||||
/*
|
/*
|
||||||
* libnl 1.1 has a bug, it tries to allocate socket numbers densely
|
* 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,
|
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
|
||||||
void *arg)
|
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 *ret = arg;
|
||||||
|
int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
|
||||||
|
|
||||||
*ret = err->error;
|
*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;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +392,7 @@ static int send_and_recv(struct nl80211_global *global,
|
||||||
void *valid_data)
|
void *valid_data)
|
||||||
{
|
{
|
||||||
struct nl_cb *cb;
|
struct nl_cb *cb;
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM, opt;
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -351,6 +401,11 @@ static int send_and_recv(struct nl80211_global *global,
|
||||||
if (!cb)
|
if (!cb)
|
||||||
goto out;
|
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);
|
err = nl_send_auto_complete(nl_handle, msg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Loading…
Reference in a new issue