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 <dimitrysh@google.com>
This commit is contained in:
Dmitry Shmidt 2012-04-07 12:23:21 +03:00 committed by Jouni Malinen
parent 61ce90857e
commit 5f97dd1c57
3 changed files with 209 additions and 100 deletions

View file

@ -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 */
/**

View file

@ -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);
}

View file

@ -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';