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:
parent
61ce90857e
commit
5f97dd1c57
3 changed files with 209 additions and 100 deletions
|
@ -139,6 +139,27 @@ extern "C" {
|
||||||
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
|
#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 */
|
/* wpa_supplicant/hostapd control interface access */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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,
|
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;
|
size_t i;
|
||||||
int ret;
|
int ret;
|
||||||
char *pos, *end;
|
char *pos, *end;
|
||||||
const u8 *ie, *ie2;
|
const u8 *ie, *ie2;
|
||||||
struct os_time now;
|
|
||||||
|
|
||||||
os_get_time(&now);
|
|
||||||
pos = buf;
|
pos = buf;
|
||||||
end = buf + buflen;
|
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);
|
if (mask & WPA_BSS_MASK_ID) {
|
||||||
for (i = 0; i < bss->ie_len; i++) {
|
ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
|
||||||
ret = os_snprintf(pos, end - pos, "%02x", *ie++);
|
|
||||||
if (ret < 0 || ret >= end - pos)
|
if (ret < 0 || ret >= end - pos)
|
||||||
return pos - buf;
|
return 0;
|
||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = os_snprintf(pos, end - pos, "\n");
|
if (mask & WPA_BSS_MASK_BSSID) {
|
||||||
if (ret < 0 || ret >= end - pos)
|
ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
|
||||||
return pos - buf;
|
MAC2STR(bss->bssid));
|
||||||
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 (ret < 0 || ret >= end - pos)
|
if (ret < 0 || ret >= end - pos)
|
||||||
return pos - buf;
|
return 0;
|
||||||
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;
|
|
||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = os_snprintf(pos, end - pos, "\n");
|
if (mask & WPA_BSS_MASK_FREQ) {
|
||||||
if (ret < 0 || ret >= end - pos)
|
ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
|
||||||
return pos - buf;
|
if (ret < 0 || ret >= end - pos)
|
||||||
pos += ret;
|
return 0;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = os_snprintf(pos, end - pos, "ssid=%s\n",
|
if (mask & WPA_BSS_MASK_BEACON_INT) {
|
||||||
wpa_ssid_txt(bss->ssid, bss->ssid_len));
|
ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
|
||||||
if (ret < 0 || ret >= end - pos)
|
bss->beacon_int);
|
||||||
return pos - buf;
|
if (ret < 0 || ret >= end - pos)
|
||||||
pos += ret;
|
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
|
#ifdef CONFIG_WPS
|
||||||
ie = (const u8 *) (bss + 1);
|
if (mask & WPA_BSS_MASK_WPS_SCAN) {
|
||||||
ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
|
ie = (const u8 *) (bss + 1);
|
||||||
if (ret < 0 || ret >= end - pos)
|
ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
|
||||||
return pos - buf;
|
if (ret < 0 || ret >= end - pos)
|
||||||
pos += ret;
|
return 0;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
ie = (const u8 *) (bss + 1);
|
if (mask & WPA_BSS_MASK_P2P_SCAN) {
|
||||||
ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
|
ie = (const u8 *) (bss + 1);
|
||||||
if (ret < 0 || ret >= end - pos)
|
ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
|
||||||
return pos - buf;
|
if (ret < 0 || ret >= end - pos)
|
||||||
pos += ret;
|
return 0;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
#ifdef CONFIG_INTERWORKING
|
#ifdef CONFIG_INTERWORKING
|
||||||
pos = anqp_add_hex(pos, end, "anqp_venue_name", bss->anqp_venue_name);
|
if (mask & WPA_BSS_MASK_INTERNETW) {
|
||||||
pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
|
pos = anqp_add_hex(pos, end, "anqp_venue_name",
|
||||||
bss->anqp_network_auth_type);
|
bss->anqp_venue_name);
|
||||||
pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
|
pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
|
||||||
bss->anqp_roaming_consortium);
|
bss->anqp_network_auth_type);
|
||||||
pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
|
pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
|
||||||
bss->anqp_ip_addr_type_availability);
|
bss->anqp_roaming_consortium);
|
||||||
pos = anqp_add_hex(pos, end, "anqp_nai_realm", bss->anqp_nai_realm);
|
pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
|
||||||
pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp);
|
bss->anqp_ip_addr_type_availability);
|
||||||
pos = anqp_add_hex(pos, end, "anqp_domain_name",
|
pos = anqp_add_hex(pos, end, "anqp_nai_realm",
|
||||||
bss->anqp_domain_name);
|
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 */
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
|
||||||
return pos - buf;
|
return pos - buf;
|
||||||
|
@ -2532,6 +2609,8 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
size_t i;
|
size_t i;
|
||||||
struct wpa_bss *bss;
|
struct wpa_bss *bss;
|
||||||
|
char *ctmp;
|
||||||
|
unsigned long mask = WPA_BSS_MASK_ALL;
|
||||||
|
|
||||||
if (os_strcmp(cmd, "FIRST") == 0)
|
if (os_strcmp(cmd, "FIRST") == 0)
|
||||||
bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
|
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)
|
if (bss == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return print_bss_info(wpa_s, bss, buf, buflen);
|
return print_bss_info(wpa_s, bss, mask, buf, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1696,13 +1696,16 @@ static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
char cmd[64];
|
char cmd[64];
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (argc != 1) {
|
if (argc < 1) {
|
||||||
printf("Invalid BSS command: need one argument (index or "
|
printf("Invalid BSS command: need at least one argument"
|
||||||
"BSSID)\n");
|
"(index or BSSID)\n");
|
||||||
return -1;
|
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))
|
if (res < 0 || (size_t) res >= sizeof(cmd))
|
||||||
return -1;
|
return -1;
|
||||||
cmd[sizeof(cmd) - 1] = '\0';
|
cmd[sizeof(cmd) - 1] = '\0';
|
||||||
|
|
Loading…
Reference in a new issue