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.
This commit is contained in:
Jouni Malinen 2010-11-06 17:11:12 +02:00
parent a149fcc77d
commit d84d389351
5 changed files with 209 additions and 4 deletions

View file

@ -39,10 +39,13 @@ endif
OBJS_lib += ../src/utils/libutils.a OBJS_lib += ../src/utils/libutils.a
OBJS_lib += ../src/crypto/libcrypto.a OBJS_lib += ../src/crypto/libcrypto.a
OBJS += ../src/common/ieee802_11_common.o
OBJS += wlantest.o OBJS += wlantest.o
OBJS += readpcap.o OBJS += readpcap.o
OBJS += monitor.o OBJS += monitor.o
OBJS += process.o OBJS += process.o
OBJS += bss.o
OBJS += crc32.o OBJS += crc32.o
LIBS += -lpcap LIBS += -lpcap

48
wlantest/bss.c Normal file
View file

@ -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);
}

View file

@ -18,6 +18,7 @@
#include "utils/radiotap.h" #include "utils/radiotap.h"
#include "utils/radiotap_iter.h" #include "utils/radiotap_iter.h"
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "wlantest.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) static void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
{ {
const struct ieee80211_hdr *hdr; 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" : "", fc & WLAN_FC_ISWEP ? " Prot" : "",
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
MAC2STR(hdr->addr3)); 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;
}
} }

View 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 main(int argc, char *argv[])
{ {
int c; int c;
@ -46,8 +64,7 @@ int main(int argc, char *argv[])
if (os_program_init()) if (os_program_init())
return -1; return -1;
os_memset(&wt, 0, sizeof(wt)); wlantest_init(&wt);
wt.monitor_sock = -1;
for (;;) { for (;;) {
c = getopt(argc, argv, "dhi:r:q"); c = getopt(argc, argv, "dhi:r:q");
@ -98,8 +115,7 @@ int main(int argc, char *argv[])
"fcs_error=%u", "fcs_error=%u",
wt.rx_mgmt, wt.rx_ctrl, wt.rx_data, wt.fcs_error); wt.rx_mgmt, wt.rx_ctrl, wt.rx_data, wt.fcs_error);
if (ifname) wlantest_deinit(&wt);
monitor_deinit(&wt);
eloop_destroy(); eloop_destroy();
os_program_deinit(); os_program_deinit();

View file

@ -15,9 +15,26 @@
#ifndef WLANTEST_H #ifndef WLANTEST_H
#define 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 { struct wlantest {
int monitor_sock; int monitor_sock;
struct dl_list bss; /* struct wlantest_bss */
unsigned int rx_mgmt; unsigned int rx_mgmt;
unsigned int rx_ctrl; unsigned int rx_ctrl;
unsigned int rx_data; 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); int monitor_init(struct wlantest *wt, const char *ifname);
void monitor_deinit(struct wlantest *wt); 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 */ #endif /* WLANTEST_H */