aboutsummaryrefslogtreecommitdiffstats
path: root/wlantest/ctrl.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2010-11-18 15:17:18 (GMT)
committerJouni Malinen <j@w1.fi>2010-11-18 15:17:18 (GMT)
commit6f2346c144f8f7ee8973f0db841558e339fb9b15 (patch)
treec5ef78c41344288295995315e04c1fa8df67bba4 /wlantest/ctrl.c
parenta6c1810297ad59fcb2261e5192a6367de6d47cee (diff)
downloadhostap-6f2346c144f8f7ee8973f0db841558e339fb9b15.zip
hostap-6f2346c144f8f7ee8973f0db841558e339fb9b15.tar.gz
hostap-6f2346c144f8f7ee8973f0db841558e339fb9b15.tar.bz2
wlantest: Add list_bss and list_sta commands
These can be used to list the current BSS and STA information maintained in wlantest.
Diffstat (limited to 'wlantest/ctrl.c')
-rw-r--r--wlantest/ctrl.c112
1 files changed, 109 insertions, 3 deletions
diff --git a/wlantest/ctrl.c b/wlantest/ctrl.c
index 3a292d6..3f88029 100644
--- a/wlantest/ctrl.c
+++ b/wlantest/ctrl.c
@@ -21,6 +21,34 @@
#include "wlantest_ctrl.h"
+static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr,
+ size_t *len)
+{
+ u8 *pos = buf;
+
+ while (pos + 8 <= buf + buflen) {
+ enum wlantest_ctrl_attr a;
+ size_t alen;
+ a = WPA_GET_BE32(pos);
+ pos += 4;
+ alen = WPA_GET_BE32(pos);
+ pos += 4;
+ if (pos + alen > buf + buflen) {
+ wpa_printf(MSG_DEBUG, "Invalid control message "
+ "attribute");
+ return NULL;
+ }
+ if (a == attr) {
+ *len = alen;
+ return pos;
+ }
+ pos += alen;
+ }
+
+ return NULL;
+}
+
+
static void ctrl_disconnect(struct wlantest *wt, int sock)
{
int i;
@@ -37,15 +65,87 @@ static void ctrl_disconnect(struct wlantest *wt, int sock)
}
+static void ctrl_send(struct wlantest *wt, int sock, const u8 *buf,
+ size_t len)
+{
+ if (send(sock, buf, len, 0) < 0) {
+ wpa_printf(MSG_INFO, "send(ctrl): %s", strerror(errno));
+ ctrl_disconnect(wt, sock);
+ }
+}
+
+
static void ctrl_send_simple(struct wlantest *wt, int sock,
enum wlantest_ctrl_cmd cmd)
{
u8 buf[4];
WPA_PUT_BE32(buf, cmd);
- if (send(sock, buf, sizeof(buf), 0) < 0) {
- wpa_printf(MSG_INFO, "send(ctrl): %s", strerror(errno));
- ctrl_disconnect(wt, sock);
+ ctrl_send(wt, sock, buf, sizeof(buf));
+}
+
+
+static void ctrl_list_bss(struct wlantest *wt, int sock)
+{
+ u8 buf[WLANTEST_CTRL_MAX_RESP_LEN], *pos, *len;
+ struct wlantest_bss *bss;
+
+ pos = buf;
+ WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS);
+ pos += 4;
+ WPA_PUT_BE32(pos, WLANTEST_ATTR_BSSID);
+ pos += 4;
+ len = pos; /* to be filled */
+ pos += 4;
+
+ dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) {
+ if (pos + ETH_ALEN > buf + WLANTEST_CTRL_MAX_RESP_LEN)
+ break;
+ os_memcpy(pos, bss->bssid, ETH_ALEN);
+ pos += ETH_ALEN;
}
+
+ WPA_PUT_BE32(len, pos - len - 4);
+ ctrl_send(wt, sock, buf, pos - buf);
+}
+
+
+static void ctrl_list_sta(struct wlantest *wt, int sock, u8 *cmd, size_t clen)
+{
+ u8 buf[WLANTEST_CTRL_MAX_RESP_LEN], *pos, *len;
+ u8 *bssid;
+ size_t bssid_len;
+ struct wlantest_bss *bss;
+ struct wlantest_sta *sta;
+
+ bssid = attr_get(cmd, clen, WLANTEST_ATTR_BSSID, &bssid_len);
+ if (bssid == NULL || bssid_len != ETH_ALEN) {
+ ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+ return;
+ }
+
+ bss = bss_get(wt, bssid);
+ if (bss == NULL) {
+ ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE);
+ return;
+ }
+
+ pos = buf;
+ WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS);
+ pos += 4;
+ WPA_PUT_BE32(pos, WLANTEST_ATTR_STA_ADDR);
+ pos += 4;
+ len = pos; /* to be filled */
+ pos += 4;
+
+ dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
+ if (pos + ETH_ALEN > buf + WLANTEST_CTRL_MAX_RESP_LEN)
+ break;
+ os_memcpy(pos, sta->addr, ETH_ALEN);
+ pos += ETH_ALEN;
+ }
+
+ WPA_PUT_BE32(len, pos - len - 4);
+ ctrl_send(wt, sock, buf, pos - buf);
}
@@ -87,6 +187,12 @@ static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx)
ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
eloop_terminate();
break;
+ case WLANTEST_CTRL_LIST_BSS:
+ ctrl_list_bss(wt, sock);
+ break;
+ case WLANTEST_CTRL_LIST_STA:
+ ctrl_list_sta(wt, sock, buf + 4, len - 4);
+ break;
default:
ctrl_send_simple(wt, sock, WLANTEST_CTRL_UNKNOWN_CMD);
break;