From 5f97dd1c57f1b72b3493ac4237b505bdd4416a57 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Sat, 7 Apr 2012 12:23:21 +0300 Subject: [PATCH] Add MASK=0xH option for the ctrl_iface BSS command This optional parameter to the BSS command can be used to select which fields are included in the output to avoid having to parse through unneeded information and to reduce the buffer size. Signed-off-by: Dmitry Shmidt --- src/common/wpa_ctrl.h | 21 +++ wpa_supplicant/ctrl_iface.c | 277 +++++++++++++++++++++++------------- wpa_supplicant/wpa_cli.c | 11 +- 3 files changed, 209 insertions(+), 100 deletions(-) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 5b4846fdf..35012e86b 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -139,6 +139,27 @@ extern "C" { #define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED " +/* BSS command information masks */ + +#define WPA_BSS_MASK_ALL 0xFFFFFFFF +#define WPA_BSS_MASK_ID BIT(0) +#define WPA_BSS_MASK_BSSID BIT(1) +#define WPA_BSS_MASK_FREQ BIT(2) +#define WPA_BSS_MASK_BEACON_INT BIT(3) +#define WPA_BSS_MASK_CAPABILITIES BIT(4) +#define WPA_BSS_MASK_QUAL BIT(5) +#define WPA_BSS_MASK_NOISE BIT(6) +#define WPA_BSS_MASK_LEVEL BIT(7) +#define WPA_BSS_MASK_TSF BIT(8) +#define WPA_BSS_MASK_AGE BIT(9) +#define WPA_BSS_MASK_IE BIT(10) +#define WPA_BSS_MASK_FLAGS BIT(11) +#define WPA_BSS_MASK_SSID BIT(12) +#define WPA_BSS_MASK_WPS_SCAN BIT(13) +#define WPA_BSS_MASK_P2P_SCAN BIT(14) +#define WPA_BSS_MASK_INTERNETW BIT(15) + + /* wpa_supplicant/hostapd control interface access */ /** diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index ad292b022..4314d6995 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2398,127 +2398,204 @@ static char * anqp_add_hex(char *pos, char *end, const char *title, static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, - char *buf, size_t buflen) + unsigned long mask, char *buf, size_t buflen) { size_t i; int ret; char *pos, *end; const u8 *ie, *ie2; - struct os_time now; - os_get_time(&now); pos = buf; end = buf + buflen; - ret = os_snprintf(pos, end - pos, - "id=%u\n" - "bssid=" MACSTR "\n" - "freq=%d\n" - "beacon_int=%d\n" - "capabilities=0x%04x\n" - "qual=%d\n" - "noise=%d\n" - "level=%d\n" - "tsf=%016llu\n" - "age=%d\n" - "ie=", - bss->id, - MAC2STR(bss->bssid), bss->freq, bss->beacon_int, - bss->caps, bss->qual, bss->noise, bss->level, - (unsigned long long) bss->tsf, - (int) (now.sec - bss->last_update.sec)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - ie = (const u8 *) (bss + 1); - for (i = 0; i < bss->ie_len; i++) { - ret = os_snprintf(pos, end - pos, "%02x", *ie++); + if (mask & WPA_BSS_MASK_ID) { + ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); if (ret < 0 || ret >= end - pos) - return pos - buf; + return 0; pos += ret; } - ret = os_snprintf(pos, end - pos, "\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - ret = os_snprintf(pos, end - pos, "flags="); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); - if (ie) - pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); - ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); - if (ie2) - pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); - pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); - if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { - ret = os_snprintf(pos, end - pos, "[WEP]"); + if (mask & WPA_BSS_MASK_BSSID) { + ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", + MAC2STR(bss->bssid)); if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (bss->caps & IEEE80211_CAP_IBSS) { - ret = os_snprintf(pos, end - pos, "[IBSS]"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (bss->caps & IEEE80211_CAP_ESS) { - ret = os_snprintf(pos, end - pos, "[ESS]"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { - ret = os_snprintf(pos, end - pos, "[P2P]"); - if (ret < 0 || ret >= end - pos) - return pos - buf; + return 0; pos += ret; } - ret = os_snprintf(pos, end - pos, "\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; + if (mask & WPA_BSS_MASK_FREQ) { + ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } - ret = os_snprintf(pos, end - pos, "ssid=%s\n", - wpa_ssid_txt(bss->ssid, bss->ssid_len)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; + if (mask & WPA_BSS_MASK_BEACON_INT) { + ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", + bss->beacon_int); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_CAPABILITIES) { + ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", + bss->caps); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_QUAL) { + ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_NOISE) { + ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_LEVEL) { + ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_TSF) { + ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", + (unsigned long long) bss->tsf); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_AGE) { + struct os_time now; + + os_get_time(&now); + ret = os_snprintf(pos, end - pos, "age=%d\n", + (int) (now.sec - bss->last_update.sec)); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_IE) { + ret = os_snprintf(pos, end - pos, "ie="); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ie = (const u8 *) (bss + 1); + for (i = 0; i < bss->ie_len; i++) { + ret = os_snprintf(pos, end - pos, "%02x", *ie++); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + ret = os_snprintf(pos, end - pos, "\n"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_FLAGS) { + ret = os_snprintf(pos, end - pos, "flags="); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); + if (ie) + pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, + 2 + ie[1]); + ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); + if (ie2) + pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, + 2 + ie2[1]); + pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); + if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { + ret = os_snprintf(pos, end - pos, "[WEP]"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + if (bss->caps & IEEE80211_CAP_IBSS) { + ret = os_snprintf(pos, end - pos, "[IBSS]"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + if (bss->caps & IEEE80211_CAP_ESS) { + ret = os_snprintf(pos, end - pos, "[ESS]"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { + ret = os_snprintf(pos, end - pos, "[P2P]"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + ret = os_snprintf(pos, end - pos, "\n"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + + if (mask & WPA_BSS_MASK_SSID) { + ret = os_snprintf(pos, end - pos, "ssid=%s\n", + wpa_ssid_txt(bss->ssid, bss->ssid_len)); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } #ifdef CONFIG_WPS - ie = (const u8 *) (bss + 1); - ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; + if (mask & WPA_BSS_MASK_WPS_SCAN) { + ie = (const u8 *) (bss + 1); + ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P - ie = (const u8 *) (bss + 1); - ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; + if (mask & WPA_BSS_MASK_P2P_SCAN) { + ie = (const u8 *) (bss + 1); + ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } #endif /* CONFIG_P2P */ #ifdef CONFIG_INTERWORKING - pos = anqp_add_hex(pos, end, "anqp_venue_name", bss->anqp_venue_name); - pos = anqp_add_hex(pos, end, "anqp_network_auth_type", - bss->anqp_network_auth_type); - pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", - bss->anqp_roaming_consortium); - pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", - bss->anqp_ip_addr_type_availability); - pos = anqp_add_hex(pos, end, "anqp_nai_realm", bss->anqp_nai_realm); - pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp); - pos = anqp_add_hex(pos, end, "anqp_domain_name", - bss->anqp_domain_name); + if (mask & WPA_BSS_MASK_INTERNETW) { + pos = anqp_add_hex(pos, end, "anqp_venue_name", + bss->anqp_venue_name); + pos = anqp_add_hex(pos, end, "anqp_network_auth_type", + bss->anqp_network_auth_type); + pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", + bss->anqp_roaming_consortium); + pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", + bss->anqp_ip_addr_type_availability); + pos = anqp_add_hex(pos, end, "anqp_nai_realm", + bss->anqp_nai_realm); + pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp); + pos = anqp_add_hex(pos, end, "anqp_domain_name", + bss->anqp_domain_name); + } #endif /* CONFIG_INTERWORKING */ return pos - buf; @@ -2532,6 +2609,8 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, u8 bssid[ETH_ALEN]; size_t i; struct wpa_bss *bss; + char *ctmp; + unsigned long mask = WPA_BSS_MASK_ALL; if (os_strcmp(cmd, "FIRST") == 0) bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list); @@ -2571,10 +2650,16 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, } } + if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { + mask = strtoul(ctmp + 5, NULL, 0x10); + if (mask == 0) + mask = WPA_BSS_MASK_ALL; + } + if (bss == NULL) return 0; - return print_bss_info(wpa_s, bss, buf, buflen); + return print_bss_info(wpa_s, bss, mask, buf, buflen); } diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 843acc756..18759abf2 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1696,13 +1696,16 @@ static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) char cmd[64]; int res; - if (argc != 1) { - printf("Invalid BSS command: need one argument (index or " - "BSSID)\n"); + if (argc < 1) { + printf("Invalid BSS command: need at least one argument" + "(index or BSSID)\n"); return -1; } - res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]); + res = os_snprintf(cmd, sizeof(cmd), "BSS %s%s%s%s%s", argv[0], + argc > 1 ? " " : "", argc > 1 ? argv[1] : "", + argc > 2 ? " " : "", argc > 2 ? argv[2] : ""); + if (res < 0 || (size_t) res >= sizeof(cmd)) return -1; cmd[sizeof(cmd) - 1] = '\0';