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:
parent
a149fcc77d
commit
d84d389351
5 changed files with 209 additions and 4 deletions
|
@ -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
48
wlantest/bss.c
Normal 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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue