diff options
author | Avraham Stern <avraham.stern@intel.com> | 2014-03-27 06:58:31 (GMT) |
---|---|---|
committer | Jouni Malinen <j@w1.fi> | 2014-03-27 13:28:44 (GMT) |
commit | 3ae8b7b7a23883a8ece546308b4ae410eed221aa (patch) | |
tree | f9ce7e09ea81542dc2c2fb176a42f66c68b6890d /hostapd | |
parent | 782e2f785e5e19b6a1d06b61a6567fc9f6c49cd4 (diff) | |
download | hostap-3ae8b7b7a23883a8ece546308b4ae410eed221aa.zip hostap-3ae8b7b7a23883a8ece546308b4ae410eed221aa.tar.gz hostap-3ae8b7b7a23883a8ece546308b4ae410eed221aa.tar.bz2 |
hostapd: Add vendor command support
Add support of vendor command to hostapd ctrl_iface.
Vendor command's format:
VENDOR <vendor id> <sub command id> [<hex formatted data>]
The 3rd argument will be converted to binary data and then passed as
argument to the sub command.
Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Diffstat (limited to 'hostapd')
-rw-r--r-- | hostapd/ctrl_iface.c | 61 | ||||
-rw-r--r-- | hostapd/hostapd_cli.c | 22 |
2 files changed, 83 insertions, 0 deletions
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 29d5d8b..4dddf80 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1281,6 +1281,63 @@ static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply, } +static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, + char *buf, size_t buflen) +{ + int ret; + char *pos; + u8 *data = NULL; + unsigned int vendor_id, subcmd; + struct wpabuf *reply; + size_t data_len = 0; + + /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ + vendor_id = strtoul(cmd, &pos, 16); + if (!isblank(*pos)) + return -EINVAL; + + subcmd = strtoul(pos, &pos, 10); + + if (*pos != '\0') { + if (!isblank(*pos++)) + return -EINVAL; + data_len = os_strlen(pos); + } + + if (data_len) { + data_len /= 2; + data = os_malloc(data_len); + if (!data) + return -ENOBUFS; + + if (hexstr2bin(pos, data, data_len)) { + wpa_printf(MSG_DEBUG, + "Vendor command: wrong parameter format"); + os_free(data); + return -EINVAL; + } + } + + reply = wpabuf_alloc((buflen - 1) / 2); + if (!reply) { + os_free(data); + return -ENOBUFS; + } + + ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, + reply); + + if (ret == 0) + ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), + wpabuf_len(reply)); + + wpabuf_free(reply); + os_free(data); + + return ret; +} + + static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx) { @@ -1486,6 +1543,10 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { if (hostapd_ctrl_iface_chan_switch(hapd, buf + 12)) reply_len = -1; + } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { + reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, + reply_size); + } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 8caca4f..c488b4f 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -940,6 +940,27 @@ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, } +static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256]; + int res; + + if (argc < 2 || argc > 3) { + printf("Invalid vendor command\n" + "usage: <vendor id> <command id> [<hex formatted command argument>]\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1], + argc == 3 ? argv[2] : ""); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long VENDOR command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + struct hostapd_cli_cmd { const char *cmd; int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); @@ -988,6 +1009,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = { { "chan_switch", hostapd_cli_cmd_chan_switch }, { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif }, { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req }, + { "vendor", hostapd_cli_cmd_vendor }, { NULL, NULL } }; |