]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: Maintain table of BSS information
authorJouni Malinen <j@w1.fi>
Sat, 6 Nov 2010 15:11:12 +0000 (17:11 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 7 Nov 2010 21:29:00 +0000 (23:29 +0200)
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
wlantest/bss.c [new file with mode: 0644]
wlantest/process.c
wlantest/wlantest.c
wlantest/wlantest.h

index b09816ad6cde0a41f7cd8220180400cb58d50fbf..983b330e1fd549c7ecbd6b90a7adf22b636a5747 100644 (file)
@@ -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 (file)
index 0000000..11b9248
--- /dev/null
@@ -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);
+}
index 93a0267ec0acd3ec9845417738771a8501ce0650..448317e84a2614ab45c153729c8d24737e9037cb 100644 (file)
@@ -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;
+       }
 }
 
 
index 9a2f70d1968bb7b70be934c3fdb91915aa5cfbfc..9856368a747aa07f835c55491eb83ebf5e176a55 100644 (file)
@@ -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();
index 2af12f1e85b2864b90ef97155b245ea6a7de83ad..a6ad4eb19ccbee5c0f7759f5ef9334ac15bbbaad 100644 (file)
 #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 */