nl80211: Extend the new vendor command for testing nl80211

CONFIG_TESTING_OPTIONS=y build of wpa_supplicant now allows arbitrary
cfg80211 commands to be performed through the new VENDOR ctrl_iface
command by using a special vendor_id ffffffff. The command identifier
(NL80211_CMD_*) is encoded as the subcmd and the attributes in the
hexformatted data area. Response attributes are returned as a hexdump.

For example, this shows a NL80211_CMD_FRAME and a response (cookie
attribute) on a little endian host:

wpa_cli -i wlan0 vendor ffffffff 59 080003004d0000000800260085090000....
0c00580000d7868c0388ffff

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2014-03-05 17:19:58 +02:00 committed by Jouni Malinen
parent b4343b9c94
commit 6b9f7af651

View file

@ -11720,6 +11720,28 @@ error:
} }
#ifdef CONFIG_TESTING_OPTIONS
static int cmd_reply_handler(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct wpabuf *buf = arg;
if (!buf)
return NL_SKIP;
if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) {
wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply");
return NL_SKIP;
}
wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0));
return NL_SKIP;
}
#endif /* CONFIG_TESTING_OPTIONS */
static int vendor_reply_handler(struct nl_msg *msg, void *arg) static int vendor_reply_handler(struct nl_msg *msg, void *arg)
{ {
struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct nlattr *tb[NL80211_ATTR_MAX + 1];
@ -11764,6 +11786,20 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
if (!msg) if (!msg)
return -ENOMEM; return -ENOMEM;
#ifdef CONFIG_TESTING_OPTIONS
if (vendor_id == 0xffffffff) {
nl80211_cmd(drv, msg, 0, subcmd);
if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) <
0)
goto nla_put_failure;
ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf);
if (ret)
wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
ret);
return ret;
}
#endif /* CONFIG_TESTING_OPTIONS */
nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR); nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
if (nl80211_set_iface_id(msg, bss) < 0) if (nl80211_set_iface_id(msg, bss) < 0)
goto nla_put_failure; goto nla_put_failure;