wlantest: Add counters and AP/direct path validation for TDLS
These can be used to write automated test scripts for verifying that TDLS STAs are using correct data path.
This commit is contained in:
parent
29ec745719
commit
0e42fff3de
5 changed files with 393 additions and 2 deletions
121
wlantest/ctrl.c
121
wlantest/ctrl.c
|
@ -192,6 +192,33 @@ static struct wlantest_sta * ctrl_get_sta(struct wlantest *wt, int sock,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wlantest_sta * ctrl_get_sta2(struct wlantest *wt, int sock,
|
||||||
|
u8 *cmd, size_t clen,
|
||||||
|
struct wlantest_bss *bss)
|
||||||
|
{
|
||||||
|
struct wlantest_sta *sta;
|
||||||
|
u8 *pos;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (bss == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pos = attr_get(cmd, clen, WLANTEST_ATTR_STA2_ADDR, &len);
|
||||||
|
if (pos == NULL || len != ETH_ALEN) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sta = sta_find(bss, pos);
|
||||||
|
if (sta == NULL) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sta;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ctrl_list_bss(struct wlantest *wt, int sock)
|
static void ctrl_list_bss(struct wlantest *wt, int sock)
|
||||||
{
|
{
|
||||||
u8 buf[WLANTEST_CTRL_MAX_RESP_LEN], *pos, *len;
|
u8 buf[WLANTEST_CTRL_MAX_RESP_LEN], *pos, *len;
|
||||||
|
@ -263,8 +290,10 @@ static void ctrl_clear_sta_counters(struct wlantest *wt, int sock, u8 *cmd,
|
||||||
|
|
||||||
bss = ctrl_get_bss(wt, sock, cmd, clen);
|
bss = ctrl_get_bss(wt, sock, cmd, clen);
|
||||||
sta = ctrl_get_sta(wt, sock, cmd, clen, bss);
|
sta = ctrl_get_sta(wt, sock, cmd, clen, bss);
|
||||||
if (sta == NULL)
|
if (sta == NULL) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
os_memset(sta->counters, 0, sizeof(sta->counters));
|
os_memset(sta->counters, 0, sizeof(sta->counters));
|
||||||
ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
|
||||||
|
@ -277,14 +306,41 @@ static void ctrl_clear_bss_counters(struct wlantest *wt, int sock, u8 *cmd,
|
||||||
struct wlantest_bss *bss;
|
struct wlantest_bss *bss;
|
||||||
|
|
||||||
bss = ctrl_get_bss(wt, sock, cmd, clen);
|
bss = ctrl_get_bss(wt, sock, cmd, clen);
|
||||||
if (bss == NULL)
|
if (bss == NULL) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
os_memset(bss->counters, 0, sizeof(bss->counters));
|
os_memset(bss->counters, 0, sizeof(bss->counters));
|
||||||
ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ctrl_clear_tdls_counters(struct wlantest *wt, int sock, u8 *cmd,
|
||||||
|
size_t clen)
|
||||||
|
{
|
||||||
|
struct wlantest_bss *bss;
|
||||||
|
struct wlantest_sta *sta;
|
||||||
|
struct wlantest_sta *sta2;
|
||||||
|
struct wlantest_tdls *tdls;
|
||||||
|
|
||||||
|
bss = ctrl_get_bss(wt, sock, cmd, clen);
|
||||||
|
sta = ctrl_get_sta(wt, sock, cmd, clen, bss);
|
||||||
|
sta2 = ctrl_get_sta2(wt, sock, cmd, clen, bss);
|
||||||
|
if (sta == NULL || sta2 == NULL) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
|
||||||
|
if ((tdls->init == sta && tdls->resp == sta2) ||
|
||||||
|
(tdls->init == sta2 && tdls->resp == sta))
|
||||||
|
os_memset(tdls->counters, 0, sizeof(tdls->counters));
|
||||||
|
}
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ctrl_get_sta_counter(struct wlantest *wt, int sock, u8 *cmd,
|
static void ctrl_get_sta_counter(struct wlantest *wt, int sock, u8 *cmd,
|
||||||
size_t clen)
|
size_t clen)
|
||||||
{
|
{
|
||||||
|
@ -355,6 +411,61 @@ static void ctrl_get_bss_counter(struct wlantest *wt, int sock, u8 *cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ctrl_get_tdls_counter(struct wlantest *wt, int sock, u8 *cmd,
|
||||||
|
size_t clen)
|
||||||
|
{
|
||||||
|
u8 *addr;
|
||||||
|
size_t addr_len;
|
||||||
|
struct wlantest_bss *bss;
|
||||||
|
struct wlantest_sta *sta;
|
||||||
|
struct wlantest_sta *sta2;
|
||||||
|
struct wlantest_tdls *tdls;
|
||||||
|
u32 counter;
|
||||||
|
u8 buf[4 + 12], *end, *pos;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
bss = ctrl_get_bss(wt, sock, cmd, clen);
|
||||||
|
sta = ctrl_get_sta(wt, sock, cmd, clen, bss);
|
||||||
|
sta2 = ctrl_get_sta2(wt, sock, cmd, clen, bss);
|
||||||
|
if (sta == NULL || sta2 == NULL) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = attr_get(cmd, clen, WLANTEST_ATTR_TDLS_COUNTER, &addr_len);
|
||||||
|
if (addr == NULL || addr_len != 4) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
counter = WPA_GET_BE32(addr);
|
||||||
|
if (counter >= NUM_WLANTEST_TDLS_COUNTER) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
|
||||||
|
if ((tdls->init == sta && tdls->resp == sta2) ||
|
||||||
|
(tdls->init == sta2 && tdls->resp == sta)) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = buf;
|
||||||
|
end = buf + sizeof(buf);
|
||||||
|
WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS);
|
||||||
|
pos += 4;
|
||||||
|
pos = attr_add_be32(pos, end, WLANTEST_ATTR_COUNTER,
|
||||||
|
tdls->counters[counter]);
|
||||||
|
ctrl_send(wt, sock, buf, pos - buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void build_mgmt_hdr(struct ieee80211_mgmt *mgmt,
|
static void build_mgmt_hdr(struct ieee80211_mgmt *mgmt,
|
||||||
struct wlantest_bss *bss, struct wlantest_sta *sta,
|
struct wlantest_bss *bss, struct wlantest_sta *sta,
|
||||||
int sender_ap, int stype)
|
int sender_ap, int stype)
|
||||||
|
@ -1096,12 +1207,18 @@ static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx)
|
||||||
case WLANTEST_CTRL_CLEAR_BSS_COUNTERS:
|
case WLANTEST_CTRL_CLEAR_BSS_COUNTERS:
|
||||||
ctrl_clear_bss_counters(wt, sock, buf + 4, len - 4);
|
ctrl_clear_bss_counters(wt, sock, buf + 4, len - 4);
|
||||||
break;
|
break;
|
||||||
|
case WLANTEST_CTRL_CLEAR_TDLS_COUNTERS:
|
||||||
|
ctrl_clear_tdls_counters(wt, sock, buf + 4, len - 4);
|
||||||
|
break;
|
||||||
case WLANTEST_CTRL_GET_STA_COUNTER:
|
case WLANTEST_CTRL_GET_STA_COUNTER:
|
||||||
ctrl_get_sta_counter(wt, sock, buf + 4, len - 4);
|
ctrl_get_sta_counter(wt, sock, buf + 4, len - 4);
|
||||||
break;
|
break;
|
||||||
case WLANTEST_CTRL_GET_BSS_COUNTER:
|
case WLANTEST_CTRL_GET_BSS_COUNTER:
|
||||||
ctrl_get_bss_counter(wt, sock, buf + 4, len - 4);
|
ctrl_get_bss_counter(wt, sock, buf + 4, len - 4);
|
||||||
break;
|
break;
|
||||||
|
case WLANTEST_CTRL_GET_TDLS_COUNTER:
|
||||||
|
ctrl_get_tdls_counter(wt, sock, buf + 4, len - 4);
|
||||||
|
break;
|
||||||
case WLANTEST_CTRL_INJECT:
|
case WLANTEST_CTRL_INJECT:
|
||||||
ctrl_inject(wt, sock, buf + 4, len - 4);
|
ctrl_inject(wt, sock, buf + 4, len - 4);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -359,6 +359,66 @@ static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *bssid,
|
||||||
|
const u8 *sta1_addr,
|
||||||
|
const u8 *sta2_addr)
|
||||||
|
{
|
||||||
|
struct wlantest_bss *bss;
|
||||||
|
struct wlantest_sta *sta1, *sta2;
|
||||||
|
struct wlantest_tdls *tdls;
|
||||||
|
|
||||||
|
bss = bss_find(wt, bssid);
|
||||||
|
if (bss == NULL)
|
||||||
|
return NULL;
|
||||||
|
sta1 = sta_find(bss, sta1_addr);
|
||||||
|
if (sta1 == NULL)
|
||||||
|
return NULL;
|
||||||
|
sta2 = sta_find(bss, sta2_addr);
|
||||||
|
if (sta2 == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
|
||||||
|
if ((tdls->init == sta1 && tdls->resp == sta2) ||
|
||||||
|
(tdls->init == sta2 && tdls->resp == sta1))
|
||||||
|
return tdls;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void add_direct_link(struct wlantest *wt, const u8 *bssid,
|
||||||
|
const u8 *sta1_addr, const u8 *sta2_addr)
|
||||||
|
{
|
||||||
|
struct wlantest_tdls *tdls;
|
||||||
|
|
||||||
|
tdls = get_tdls(wt, bssid, sta1_addr, sta2_addr);
|
||||||
|
if (tdls == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tdls->link_up)
|
||||||
|
tdls->counters[WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK]++;
|
||||||
|
else
|
||||||
|
tdls->counters[WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void add_ap_path(struct wlantest *wt, const u8 *bssid,
|
||||||
|
const u8 *sta1_addr, const u8 *sta2_addr)
|
||||||
|
{
|
||||||
|
struct wlantest_tdls *tdls;
|
||||||
|
|
||||||
|
tdls = get_tdls(wt, bssid, sta1_addr, sta2_addr);
|
||||||
|
if (tdls == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tdls->link_up)
|
||||||
|
tdls->counters[WLANTEST_TDLS_COUNTER_INVALID_AP_PATH]++;
|
||||||
|
else
|
||||||
|
tdls->counters[WLANTEST_TDLS_COUNTER_VALID_AP_PATH]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void rx_data(struct wlantest *wt, const u8 *data, size_t len)
|
void rx_data(struct wlantest *wt, const u8 *data, size_t len)
|
||||||
{
|
{
|
||||||
const struct ieee80211_hdr *hdr;
|
const struct ieee80211_hdr *hdr;
|
||||||
|
@ -393,6 +453,7 @@ void rx_data(struct wlantest *wt, const u8 *data, size_t len)
|
||||||
fc & WLAN_FC_ISWEP ? " Prot" : "",
|
fc & WLAN_FC_ISWEP ? " Prot" : "",
|
||||||
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
|
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
|
||||||
MAC2STR(hdr->addr3));
|
MAC2STR(hdr->addr3));
|
||||||
|
add_direct_link(wt, hdr->addr3, hdr->addr1, hdr->addr2);
|
||||||
rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
|
rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
|
||||||
data + hdrlen, len - hdrlen);
|
data + hdrlen, len - hdrlen);
|
||||||
break;
|
break;
|
||||||
|
@ -404,6 +465,7 @@ void rx_data(struct wlantest *wt, const u8 *data, size_t len)
|
||||||
fc & WLAN_FC_ISWEP ? " Prot" : "",
|
fc & WLAN_FC_ISWEP ? " Prot" : "",
|
||||||
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
|
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
|
||||||
MAC2STR(hdr->addr3));
|
MAC2STR(hdr->addr3));
|
||||||
|
add_ap_path(wt, hdr->addr2, hdr->addr1, hdr->addr3);
|
||||||
rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
|
rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
|
||||||
data + hdrlen, len - hdrlen);
|
data + hdrlen, len - hdrlen);
|
||||||
break;
|
break;
|
||||||
|
@ -415,6 +477,7 @@ void rx_data(struct wlantest *wt, const u8 *data, size_t len)
|
||||||
fc & WLAN_FC_ISWEP ? " Prot" : "",
|
fc & WLAN_FC_ISWEP ? " Prot" : "",
|
||||||
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
|
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
|
||||||
MAC2STR(hdr->addr3));
|
MAC2STR(hdr->addr3));
|
||||||
|
add_ap_path(wt, hdr->addr1, hdr->addr3, hdr->addr2);
|
||||||
rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2,
|
rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2,
|
||||||
data + hdrlen, len - hdrlen);
|
data + hdrlen, len - hdrlen);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -96,6 +96,7 @@ struct wlantest_tdls {
|
||||||
u8 dialog_token;
|
u8 dialog_token;
|
||||||
u8 rsc_init[16 + 1][6];
|
u8 rsc_init[16 + 1][6];
|
||||||
u8 rsc_resp[16 + 1][6];
|
u8 rsc_resp[16 + 1][6];
|
||||||
|
u32 counters[NUM_WLANTEST_TDLS_COUNTER];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlantest_bss {
|
struct wlantest_bss {
|
||||||
|
|
|
@ -430,6 +430,81 @@ static char ** complete_clear_bss_counters(int s, const char *str, int pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cmd_clear_tdls_counters(int s, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
|
||||||
|
u8 buf[100], *pos;
|
||||||
|
int rlen;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
printf("clear_tdls_counters needs three arguments: BSSID, "
|
||||||
|
"STA1 address, STA2 address\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = buf;
|
||||||
|
WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_TDLS_COUNTERS);
|
||||||
|
pos += 4;
|
||||||
|
WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
|
||||||
|
pos += 4;
|
||||||
|
WPA_PUT_BE32(pos, ETH_ALEN);
|
||||||
|
pos += 4;
|
||||||
|
if (hwaddr_aton(argv[0], pos) < 0) {
|
||||||
|
printf("Invalid BSSID '%s'\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
|
WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR);
|
||||||
|
pos += 4;
|
||||||
|
WPA_PUT_BE32(pos, ETH_ALEN);
|
||||||
|
pos += 4;
|
||||||
|
if (hwaddr_aton(argv[1], pos) < 0) {
|
||||||
|
printf("Invalid STA1 address '%s'\n", argv[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
|
WPA_PUT_BE32(pos, WLANTEST_ATTR_STA2_ADDR);
|
||||||
|
pos += 4;
|
||||||
|
WPA_PUT_BE32(pos, ETH_ALEN);
|
||||||
|
pos += 4;
|
||||||
|
if (hwaddr_aton(argv[2], pos) < 0) {
|
||||||
|
printf("Invalid STA2 address '%s'\n", argv[2]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
|
rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
|
||||||
|
if (rlen < 0)
|
||||||
|
return -1;
|
||||||
|
printf("OK\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char ** complete_clear_tdls_counters(int s, const char *str, int pos)
|
||||||
|
{
|
||||||
|
int arg = get_cmd_arg_num(str, pos);
|
||||||
|
char **res = NULL;
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
|
||||||
|
switch (arg) {
|
||||||
|
case 1:
|
||||||
|
res = get_bssid_list(s);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
|
||||||
|
break;
|
||||||
|
res = get_sta_list(s, addr, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct sta_counters {
|
struct sta_counters {
|
||||||
const char *name;
|
const char *name;
|
||||||
enum wlantest_sta_counter num;
|
enum wlantest_sta_counter num;
|
||||||
|
@ -654,6 +729,120 @@ static char ** complete_get_bss_counter(int s, const char *str, int pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct tdls_counters {
|
||||||
|
const char *name;
|
||||||
|
enum wlantest_tdls_counter num;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tdls_counters tdls_counters[] = {
|
||||||
|
{ "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK },
|
||||||
|
{ "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK },
|
||||||
|
{ "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH },
|
||||||
|
{ "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cmd_get_tdls_counter(int s, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
|
||||||
|
u8 buf[100], *end, *pos;
|
||||||
|
int rlen, i;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (argc != 4) {
|
||||||
|
printf("get_tdls_counter needs four arguments: "
|
||||||
|
"counter name, BSSID, STA1 address, STA2 address\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = buf;
|
||||||
|
end = buf + sizeof(buf);
|
||||||
|
WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
for (i = 0; tdls_counters[i].name; i++) {
|
||||||
|
if (os_strcasecmp(tdls_counters[i].name, argv[0]) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (tdls_counters[i].name == NULL) {
|
||||||
|
printf("Unknown TDLS counter '%s'\n", argv[0]);
|
||||||
|
printf("Counters:");
|
||||||
|
for (i = 0; tdls_counters[i].name; i++)
|
||||||
|
printf(" %s", tdls_counters[i].name);
|
||||||
|
printf("\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER,
|
||||||
|
tdls_counters[i].num);
|
||||||
|
pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
|
||||||
|
if (hwaddr_aton(argv[1], pos) < 0) {
|
||||||
|
printf("Invalid BSSID '%s'\n", argv[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
|
pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
|
||||||
|
if (hwaddr_aton(argv[2], pos) < 0) {
|
||||||
|
printf("Invalid STA1 address '%s'\n", argv[2]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
|
pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR, ETH_ALEN);
|
||||||
|
if (hwaddr_aton(argv[3], pos) < 0) {
|
||||||
|
printf("Invalid STA2 address '%s'\n", argv[3]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
|
rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
|
||||||
|
if (rlen < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
|
||||||
|
if (pos == NULL || len != 4)
|
||||||
|
return -1;
|
||||||
|
printf("%u\n", WPA_GET_BE32(pos));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char ** complete_get_tdls_counter(int s, const char *str, int pos)
|
||||||
|
{
|
||||||
|
int arg = get_cmd_arg_num(str, pos);
|
||||||
|
char **res = NULL;
|
||||||
|
int i, count;
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
|
||||||
|
switch (arg) {
|
||||||
|
case 1:
|
||||||
|
/* counter list */
|
||||||
|
count = sizeof(tdls_counters) / sizeof(tdls_counters[0]);
|
||||||
|
res = os_zalloc(count * sizeof(char *));
|
||||||
|
if (res == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0; tdls_counters[i].name; i++) {
|
||||||
|
res[i] = os_strdup(tdls_counters[i].name);
|
||||||
|
if (res[i] == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
res = get_bssid_list(s);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
|
||||||
|
break;
|
||||||
|
res = get_sta_list(s, addr, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct inject_frames {
|
struct inject_frames {
|
||||||
const char *name;
|
const char *name;
|
||||||
enum wlantest_inject_frame frame;
|
enum wlantest_inject_frame frame;
|
||||||
|
@ -1254,6 +1443,15 @@ static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
|
||||||
{ "info_bss", cmd_info_bss,
|
{ "info_bss", cmd_info_bss,
|
||||||
"<field> <BSSID> = get BSS information",
|
"<field> <BSSID> = get BSS information",
|
||||||
complete_info_bss },
|
complete_info_bss },
|
||||||
|
{ "clear_tdls_counters", cmd_clear_tdls_counters,
|
||||||
|
"<BSSID> <STA1> <STA2> = clear TDLS counters",
|
||||||
|
complete_clear_tdls_counters },
|
||||||
|
{ "get_tdls_counter", cmd_get_tdls_counter,
|
||||||
|
"<counter> <BSSID> <STA1> <STA2> = get TDLS counter value",
|
||||||
|
complete_get_tdls_counter },
|
||||||
|
{ "get_bss_counter", cmd_get_bss_counter,
|
||||||
|
"<counter> <BSSID> = get BSS counter value",
|
||||||
|
complete_get_bss_counter },
|
||||||
{ NULL, NULL, NULL, NULL }
|
{ NULL, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@ enum wlantest_ctrl_cmd {
|
||||||
WLANTEST_CTRL_INFO_STA,
|
WLANTEST_CTRL_INFO_STA,
|
||||||
WLANTEST_CTRL_INFO_BSS,
|
WLANTEST_CTRL_INFO_BSS,
|
||||||
WLANTEST_CTRL_SEND,
|
WLANTEST_CTRL_SEND,
|
||||||
|
WLANTEST_CTRL_CLEAR_TDLS_COUNTERS,
|
||||||
|
WLANTEST_CTRL_GET_TDLS_COUNTER,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wlantest_ctrl_attr {
|
enum wlantest_ctrl_attr {
|
||||||
|
@ -56,6 +58,8 @@ enum wlantest_ctrl_attr {
|
||||||
WLANTEST_ATTR_BSS_INFO,
|
WLANTEST_ATTR_BSS_INFO,
|
||||||
WLANTEST_ATTR_INFO,
|
WLANTEST_ATTR_INFO,
|
||||||
WLANTEST_ATTR_FRAME,
|
WLANTEST_ATTR_FRAME,
|
||||||
|
WLANTEST_ATTR_TDLS_COUNTER,
|
||||||
|
WLANTEST_ATTR_STA2_ADDR,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wlantest_bss_counter {
|
enum wlantest_bss_counter {
|
||||||
|
@ -95,6 +99,14 @@ enum wlantest_sta_counter {
|
||||||
NUM_WLANTEST_STA_COUNTER
|
NUM_WLANTEST_STA_COUNTER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum wlantest_tdls_counter {
|
||||||
|
WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK,
|
||||||
|
WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK,
|
||||||
|
WLANTEST_TDLS_COUNTER_VALID_AP_PATH,
|
||||||
|
WLANTEST_TDLS_COUNTER_INVALID_AP_PATH,
|
||||||
|
NUM_WLANTEST_TDLS_COUNTER
|
||||||
|
};
|
||||||
|
|
||||||
enum wlantest_inject_frame {
|
enum wlantest_inject_frame {
|
||||||
WLANTEST_FRAME_AUTH,
|
WLANTEST_FRAME_AUTH,
|
||||||
WLANTEST_FRAME_ASSOCREQ,
|
WLANTEST_FRAME_ASSOCREQ,
|
||||||
|
|
Loading…
Reference in a new issue