From d84d38935127dc6f64ed1c1b8aa986e85d99c9b6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Nov 2010 17:11:12 +0200 Subject: [PATCH] wlantest: Maintain table of BSS information Whenever a Beacon or Probe Response frame is observed, add or update a BSS entry to maintain current information about the active BSSes. --- wlantest/Makefile | 3 ++ wlantest/bss.c | 48 ++++++++++++++++++ wlantest/process.c | 118 ++++++++++++++++++++++++++++++++++++++++++++ wlantest/wlantest.c | 24 +++++++-- wlantest/wlantest.h | 20 ++++++++ 5 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 wlantest/bss.c diff --git a/wlantest/Makefile b/wlantest/Makefile index b09816ad6..983b330e1 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 000000000..11b9248c7 --- /dev/null +++ b/wlantest/bss.c @@ -0,0 +1,48 @@ +/* + * BSS list + * Copyright (c) 2010, Jouni Malinen + * + * 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 93a0267ec..448317e84 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 9a2f70d19..9856368a7 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 2af12f1e8..a6ad4eb19 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 */