aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--wlantest/Makefile3
-rw-r--r--wlantest/bss.c48
-rw-r--r--wlantest/process.c118
-rw-r--r--wlantest/wlantest.c24
-rw-r--r--wlantest/wlantest.h20
5 files changed, 209 insertions, 4 deletions
diff --git a/wlantest/Makefile b/wlantest/Makefile
index b09816a..983b330 100644
--- a/wlantest/Makefile
+++ b/wlantest/Makefile
@@ -39,10 +39,13 @@ endif
OBJS_lib += ../src/utils/libutils.a
OBJS_lib += ../src/crypto/libcrypto.a
+OBJS += ../src/common/ieee802_11_common.o
+
OBJS += wlantest.o
OBJS += readpcap.o
OBJS += monitor.o
OBJS += process.o
+OBJS += bss.o
OBJS += crc32.o
LIBS += -lpcap
diff --git a/wlantest/bss.c b/wlantest/bss.c
new file mode 100644
index 0000000..11b9248
--- /dev/null
+++ b/wlantest/bss.c
@@ -0,0 +1,48 @@
+/*
+ * BSS list
+ * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "wlantest.h"
+
+
+struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid)
+{
+ struct wlantest_bss *bss;
+
+ if (bssid[0] & 0x01)
+ return NULL; /* Skip group addressed frames */
+
+ dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) {
+ if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
+ return bss;
+ }
+
+ bss = os_zalloc(sizeof(*bss));
+ if (bss == NULL)
+ return NULL;
+ os_memcpy(bss->bssid, bssid, ETH_ALEN);
+ dl_list_add(&wt->bss, &bss->list);
+ wpa_printf(MSG_DEBUG, "Discovered new BSS - " MACSTR,
+ MAC2STR(bss->bssid));
+ return bss;
+}
+
+
+void bss_deinit(struct wlantest_bss *bss)
+{
+ dl_list_del(&bss->list);
+ os_free(bss);
+}
diff --git a/wlantest/process.c b/wlantest/process.c
index 93a0267..448317e 100644
--- a/wlantest/process.c
+++ b/wlantest/process.c
@@ -18,6 +18,7 @@
#include "utils/radiotap.h"
#include "utils/radiotap_iter.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
#include "wlantest.h"
@@ -53,6 +54,114 @@ static const char * mgmt_stype(u16 stype)
}
+static void bss_update(struct wlantest_bss *bss,
+ struct ieee802_11_elems *elems)
+{
+ if (elems->ssid == NULL || elems->ssid_len > 32) {
+ wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon "
+ "frame for " MACSTR, MAC2STR(bss->bssid));
+ bss->parse_error_reported = 1;
+ return;
+ }
+
+ os_memcpy(bss->ssid, elems->ssid, elems->ssid_len);
+ bss->ssid_len = elems->ssid_len;
+
+ if (elems->rsn_ie == NULL) {
+ if (bss->rsnie[0]) {
+ wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE removed",
+ MAC2STR(bss->bssid));
+ bss->rsnie[0] = 0;
+ }
+ } else {
+ if (bss->rsnie[0] == 0 ||
+ os_memcmp(bss->rsnie, elems->rsn_ie - 2,
+ elems->rsn_ie_len + 2) != 0) {
+ wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE "
+ "stored", MAC2STR(bss->bssid));
+ wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2,
+ elems->rsn_ie_len + 2);
+ }
+ os_memcpy(bss->rsnie, elems->rsn_ie - 2,
+ elems->rsn_ie_len + 2);
+ }
+
+ if (elems->wpa_ie == NULL) {
+ if (bss->wpaie[0]) {
+ wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE removed",
+ MAC2STR(bss->bssid));
+ bss->wpaie[0] = 0;
+ }
+ } else {
+ if (bss->wpaie[0] == 0 ||
+ os_memcmp(bss->wpaie, elems->wpa_ie - 2,
+ elems->wpa_ie_len + 2) != 0) {
+ wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE "
+ "stored", MAC2STR(bss->bssid));
+ wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2,
+ elems->wpa_ie_len + 2);
+ }
+ os_memcpy(bss->wpaie, elems->wpa_ie - 2,
+ elems->wpa_ie_len + 2);
+ }
+}
+
+
+static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
+{
+ const struct ieee80211_mgmt *mgmt;
+ struct wlantest_bss *bss;
+ struct ieee802_11_elems elems;
+
+ mgmt = (const struct ieee80211_mgmt *) data;
+ bss = bss_get(wt, mgmt->bssid);
+ if (bss == NULL)
+ return;
+ if (bss->proberesp_seen)
+ return; /* do not override with Beacon data */
+ bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info);
+ if (ieee802_11_parse_elems(mgmt->u.beacon.variable,
+ len - (mgmt->u.beacon.variable - data),
+ &elems, 0) == ParseFailed) {
+ if (bss->parse_error_reported)
+ return;
+ wpa_printf(MSG_INFO, "Invalid IEs in a Beacon frame from "
+ MACSTR, MAC2STR(mgmt->sa));
+ bss->parse_error_reported = 1;
+ return;
+ }
+
+ bss_update(bss, &elems);
+}
+
+
+static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len)
+{
+ const struct ieee80211_mgmt *mgmt;
+ struct wlantest_bss *bss;
+ struct ieee802_11_elems elems;
+
+ mgmt = (const struct ieee80211_mgmt *) data;
+ bss = bss_get(wt, mgmt->bssid);
+ if (bss == NULL)
+ return;
+
+ bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info);
+ if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
+ len - (mgmt->u.probe_resp.variable - data),
+ &elems, 0) == ParseFailed) {
+ if (bss->parse_error_reported)
+ return;
+ wpa_printf(MSG_INFO, "Invalid IEs in a Probe Response frame "
+ "from " MACSTR, MAC2STR(mgmt->sa));
+ bss->parse_error_reported = 1;
+ return;
+ }
+
+ bss_update(bss, &elems);
+}
+
+
static void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
{
const struct ieee80211_hdr *hdr;
@@ -76,6 +185,15 @@ static void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
fc & WLAN_FC_ISWEP ? " Prot" : "",
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
MAC2STR(hdr->addr3));
+
+ switch (stype) {
+ case WLAN_FC_STYPE_BEACON:
+ rx_mgmt_beacon(wt, data, len);
+ break;
+ case WLAN_FC_STYPE_PROBE_RESP:
+ rx_mgmt_probe_resp(wt, data, len);
+ break;
+ }
}
diff --git a/wlantest/wlantest.c b/wlantest/wlantest.c
index 9a2f70d..9856368 100644
--- a/wlantest/wlantest.c
+++ b/wlantest/wlantest.c
@@ -34,6 +34,24 @@ static void usage(void)
}
+static void wlantest_init(struct wlantest *wt)
+{
+ os_memset(wt, 0, sizeof(*wt));
+ wt->monitor_sock = -1;
+ dl_list_init(&wt->bss);
+}
+
+
+static void wlantest_deinit(struct wlantest *wt)
+{
+ struct wlantest_bss *bss, *n;
+ if (wt->monitor_sock >= 0)
+ monitor_deinit(wt);
+ dl_list_for_each_safe(bss, n, &wt->bss, struct wlantest_bss, list)
+ bss_deinit(bss);
+}
+
+
int main(int argc, char *argv[])
{
int c;
@@ -46,8 +64,7 @@ int main(int argc, char *argv[])
if (os_program_init())
return -1;
- os_memset(&wt, 0, sizeof(wt));
- wt.monitor_sock = -1;
+ wlantest_init(&wt);
for (;;) {
c = getopt(argc, argv, "dhi:r:q");
@@ -98,8 +115,7 @@ int main(int argc, char *argv[])
"fcs_error=%u",
wt.rx_mgmt, wt.rx_ctrl, wt.rx_data, wt.fcs_error);
- if (ifname)
- monitor_deinit(&wt);
+ wlantest_deinit(&wt);
eloop_destroy();
os_program_deinit();
diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h
index 2af12f1..a6ad4eb 100644
--- a/wlantest/wlantest.h
+++ b/wlantest/wlantest.h
@@ -15,9 +15,26 @@
#ifndef WLANTEST_H
#define WLANTEST_H
+#include "utils/list.h"
+
+
+struct wlantest_bss {
+ struct dl_list list;
+ u8 bssid[ETH_ALEN];
+ u16 capab_info;
+ u8 ssid[32];
+ size_t ssid_len;
+ int proberesp_seen;
+ int parse_error_reported;
+ u8 wpaie[257];
+ u8 rsnie[257];
+};
+
struct wlantest {
int monitor_sock;
+ struct dl_list bss; /* struct wlantest_bss */
+
unsigned int rx_mgmt;
unsigned int rx_ctrl;
unsigned int rx_data;
@@ -30,4 +47,7 @@ u32 crc32(const u8 *frame, size_t frame_len);
int monitor_init(struct wlantest *wt, const char *ifname);
void monitor_deinit(struct wlantest *wt);
+struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid);
+void bss_deinit(struct wlantest_bss *bss);
+
#endif /* WLANTEST_H */