From 4d7aab78bd11d6ff15f769761221e67b1160e562 Mon Sep 17 00:00:00 2001 From: Erik Ljungberg Date: Mon, 4 Jul 2016 11:25:39 +0200 Subject: [PATCH] Make driver flags available through control interface This shows the current set of driver flags in wpa_cli and hostapd_cli. Signed-off-by: Erik Ljungberg --- hostapd/ctrl_iface.c | 31 ++++++++++++++++++++++ hostapd/hostapd_cli.c | 8 ++++++ src/drivers/driver.h | 2 ++ src/drivers/driver_common.c | 52 +++++++++++++++++++++++++++++++++++++ wpa_supplicant/ctrl_iface.c | 31 ++++++++++++++++++++++ wpa_supplicant/wpa_cli.c | 10 +++++++ 6 files changed, 134 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 62bef18bc..4e7b58ec5 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2254,6 +2254,34 @@ static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, } +static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, + size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) iface->drv_flags); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (iface->drv_flags & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, char *buf, char *reply, int reply_size, @@ -2510,6 +2538,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) { if (hostapd_ctrl_iface_req_range(hapd, buf + 10)) reply_len = -1; + } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { + reply_len = hostapd_ctrl_driver_flags(hapd->iface, 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 ff133f6ae..5c1f297b0 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1218,6 +1218,13 @@ static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc, } +static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); +} + + struct hostapd_cli_cmd { const char *cmd; int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); @@ -1283,6 +1290,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { { "remove_neighbor", hostapd_cli_cmd_remove_neighbor }, { "req_lci", hostapd_cli_cmd_req_lci }, { "req_range", hostapd_cli_cmd_req_range }, + { "driver_flags", hostapd_cli_cmd_driver_flags }, { NULL, NULL } }; diff --git a/src/drivers/driver.h b/src/drivers/driver.h index d7b6a2649..97aa7c6a6 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4916,6 +4916,8 @@ int vht_supported(const struct hostapd_hw_modes *mode); struct wowlan_triggers * wpa_get_wowlan_triggers(const char *wowlan_triggers, const struct wpa_driver_capa *capa); +/* Convert driver flag to string */ +const char * driver_flag_to_string(u64 flag); /* NULL terminated array of linked in driver wrappers */ extern const struct wpa_driver_ops *const wpa_drivers[]; diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index a1141ab93..c7107ba89 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -219,3 +219,55 @@ out: os_free(buf); return triggers; } + + +const char * driver_flag_to_string(u64 flag) +{ +#define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x + switch (flag) { + DF2S(DRIVER_IE); + DF2S(SET_KEYS_AFTER_ASSOC); + DF2S(DFS_OFFLOAD); + DF2S(4WAY_HANDSHAKE); + DF2S(WIRED); + DF2S(SME); + DF2S(AP); + DF2S(SET_KEYS_AFTER_ASSOC_DONE); + DF2S(HT_2040_COEX); + DF2S(P2P_CONCURRENT); + DF2S(P2P_DEDICATED_INTERFACE); + DF2S(P2P_CAPABLE); + DF2S(AP_TEARDOWN_SUPPORT); + DF2S(P2P_MGMT_AND_NON_P2P); + DF2S(SANE_ERROR_CODES); + DF2S(OFFCHANNEL_TX); + DF2S(EAPOL_TX_STATUS); + DF2S(DEAUTH_TX_STATUS); + DF2S(BSS_SELECTION); + DF2S(TDLS_SUPPORT); + DF2S(TDLS_EXTERNAL_SETUP); + DF2S(PROBE_RESP_OFFLOAD); + DF2S(AP_UAPSD); + DF2S(INACTIVITY_TIMER); + DF2S(AP_MLME); + DF2S(SAE); + DF2S(OBSS_SCAN); + DF2S(IBSS); + DF2S(RADAR); + DF2S(DEDICATED_P2P_DEVICE); + DF2S(QOS_MAPPING); + DF2S(AP_CSA); + DF2S(MESH); + DF2S(ACS_OFFLOAD); + DF2S(KEY_MGMT_OFFLOAD); + DF2S(TDLS_CHANNEL_SWITCH); + DF2S(HT_IBSS); + DF2S(VHT_IBSS); + DF2S(SUPPORT_HW_MODE_ANY); + DF2S(OFFCHANNEL_SIMULTANEOUS); + DF2S(FULL_AP_CLIENT_STATE); + DF2S(P2P_LISTEN_OFFLOAD); + } + return "UNKNOWN"; +#undef DF2S +} diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index b75587ead..4aa0f24cf 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -6998,6 +6998,34 @@ static int wpas_ctrl_iface_get_pref_freq_list( } +static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, + char *buf, size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) wpa_s->drv_flags); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (wpa_s->drv_flags & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) { @@ -9271,6 +9299,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) reply_len = -1; #endif /* CONFIG_AUTOSCAN */ + } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { + reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, + reply_size); #ifdef ANDROID } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index ede66b773..7012dfbe5 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -711,6 +711,13 @@ static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); +} + + static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_cli_cmd(ctrl, "GET", 1, argc, argv); @@ -2963,6 +2970,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "get", wpa_cli_cmd_get, wpa_cli_complete_get, cli_cmd_flag_none, " = get information" }, + { "driver_flags", wpa_cli_cmd_driver_flags, NULL, + cli_cmd_flag_none, + "= list driver flags" }, { "logon", wpa_cli_cmd_logon, NULL, cli_cmd_flag_none, "= IEEE 802.1X EAPOL state machine logon" },