mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-25 00:38:24 -05:00
Add optional scan result filter based on SSID
filter_ssids=1 global configuration parameter can now be used to enable scan result filtering (with -Dnl80211 only for now) based on the configured SSIDs. In other words, only the scan results that have an SSID matching with one of the configured networks are included in the BSS table. This can be used to reduce memory needs in environments that have huge number of APs.
This commit is contained in:
parent
c9c38b0996
commit
3812464cda
@ -237,6 +237,30 @@ struct wpa_driver_scan_params {
|
||||
* The frequency is set in MHz. The array is zero-terminated.
|
||||
*/
|
||||
int *freqs;
|
||||
|
||||
/**
|
||||
* filter_ssids - Filter for reporting SSIDs
|
||||
*
|
||||
* This optional parameter can be used to request the driver wrapper to
|
||||
* filter scan results to include only the specified SSIDs. %NULL
|
||||
* indicates that no filtering is to be done. This can be used to
|
||||
* reduce memory needs for scan results in environments that have large
|
||||
* number of APs with different SSIDs.
|
||||
*
|
||||
* The driver wrapper is allowed to take this allocated buffer into its
|
||||
* own use by setting the pointer to %NULL. In that case, the driver
|
||||
* wrapper is responsible for freeing the buffer with os_free() once it
|
||||
* is not needed anymore.
|
||||
*/
|
||||
struct wpa_driver_scan_filter {
|
||||
u8 ssid[32];
|
||||
size_t ssid_len;
|
||||
} *filter_ssids;
|
||||
|
||||
/**
|
||||
* num_filter_ssids - Number of entries in filter_ssids array
|
||||
*/
|
||||
size_t num_filter_ssids;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -108,6 +108,9 @@ struct wpa_driver_nl80211_data {
|
||||
u64 remain_on_chan_cookie;
|
||||
u64 send_action_cookie;
|
||||
|
||||
struct wpa_driver_scan_filter *filter_ssids;
|
||||
size_t num_filter_ssids;
|
||||
|
||||
#ifdef HOSTAPD
|
||||
int eapol_sock; /* socket for EAPOL frames */
|
||||
|
||||
@ -1471,6 +1474,8 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_probe_req_report_timeout,
|
||||
drv, NULL);
|
||||
|
||||
os_free(drv->filter_ssids);
|
||||
|
||||
os_free(drv);
|
||||
}
|
||||
|
||||
@ -1519,6 +1524,11 @@ static int wpa_driver_nl80211_scan(void *priv,
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_free(drv->filter_ssids);
|
||||
drv->filter_ssids = params->filter_ssids;
|
||||
params->filter_ssids = NULL;
|
||||
drv->num_filter_ssids = params->num_filter_ssids;
|
||||
|
||||
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
|
||||
NL80211_CMD_TRIGGER_SCAN, 0);
|
||||
|
||||
@ -1598,6 +1608,57 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
|
||||
static const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
|
||||
if (ies == NULL)
|
||||
return NULL;
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
if (pos[0] == ie)
|
||||
return pos;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
|
||||
const u8 *ie, size_t ie_len)
|
||||
{
|
||||
const u8 *ssid;
|
||||
size_t i;
|
||||
|
||||
if (drv->filter_ssids == NULL)
|
||||
return 0;
|
||||
|
||||
ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID);
|
||||
if (ssid == NULL)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < drv->num_filter_ssids; i++) {
|
||||
if (ssid[1] == drv->filter_ssids[i].ssid_len &&
|
||||
os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==
|
||||
0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct nl80211_bss_info_arg {
|
||||
struct wpa_driver_nl80211_data *drv;
|
||||
struct wpa_scan_results *res;
|
||||
};
|
||||
|
||||
static int bss_info_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
||||
@ -1616,7 +1677,8 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
|
||||
[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
|
||||
[NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
|
||||
};
|
||||
struct wpa_scan_results *res = arg;
|
||||
struct nl80211_bss_info_arg *_arg = arg;
|
||||
struct wpa_scan_results *res = _arg->res;
|
||||
struct wpa_scan_res **tmp;
|
||||
struct wpa_scan_res *r;
|
||||
const u8 *ie, *beacon_ie;
|
||||
@ -1645,6 +1707,10 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
|
||||
beacon_ie_len = 0;
|
||||
}
|
||||
|
||||
if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie,
|
||||
ie ? ie_len : beacon_ie_len))
|
||||
return NL_SKIP;
|
||||
|
||||
r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
|
||||
if (r == NULL)
|
||||
return NL_SKIP;
|
||||
@ -1793,6 +1859,7 @@ nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
|
||||
struct nl_msg *msg;
|
||||
struct wpa_scan_results *res;
|
||||
int ret;
|
||||
struct nl80211_bss_info_arg arg;
|
||||
|
||||
res = os_zalloc(sizeof(*res));
|
||||
if (res == NULL)
|
||||
@ -1805,7 +1872,9 @@ nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
|
||||
NL80211_CMD_GET_SCAN, 0);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||
|
||||
ret = send_and_recv_msgs(drv, msg, bss_info_handler, res);
|
||||
arg.drv = drv;
|
||||
arg.res = res;
|
||||
ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
|
||||
msg = NULL;
|
||||
if (ret == 0) {
|
||||
wpa_printf(MSG_DEBUG, "Received scan results (%lu BSSes)",
|
||||
|
@ -337,6 +337,14 @@ struct wpa_config {
|
||||
* bss_max_count - Maximum number of BSS entries to keep in memory
|
||||
*/
|
||||
unsigned int bss_max_count;
|
||||
|
||||
/**
|
||||
* filter_ssids - SSID-based scan result filtering
|
||||
*
|
||||
* 0 = do not filter scan results
|
||||
* 1 = only include configured SSIDs in scan results/BSS table
|
||||
*/
|
||||
int filter_ssids;
|
||||
};
|
||||
|
||||
|
||||
|
@ -458,7 +458,8 @@ static const struct global_parse_data global_fields[] = {
|
||||
{ INT_RANGE(wps_cred_processing, 0, 2) },
|
||||
#endif /* CONFIG_WPS */
|
||||
{ FUNC(country) },
|
||||
{ INT(bss_max_count) }
|
||||
{ INT(bss_max_count) },
|
||||
{ INT_RANGE(filter_ssids, 0, 1) }
|
||||
};
|
||||
|
||||
#undef FUNC
|
||||
@ -892,6 +893,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
|
||||
}
|
||||
if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT)
|
||||
fprintf(f, "bss_max_count=%u\n", config->bss_max_count);
|
||||
if (config->filter_ssids)
|
||||
fprintf(f, "filter_ssids=%d\n", config->filter_ssids);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NO_CONFIG_WRITE */
|
||||
|
@ -259,6 +259,8 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk)
|
||||
|
||||
wpa_config_read_reg_dword(hk, TEXT("bss_max_count"),
|
||||
&config->bss_max_count);
|
||||
wpa_config_read_reg_dword(hk, TEXT("filter_ssids"),
|
||||
&config->filter_ssids);
|
||||
|
||||
return errors ? -1 : 0;
|
||||
}
|
||||
@ -589,6 +591,8 @@ static int wpa_config_write_global(struct wpa_config *config, HKEY hk)
|
||||
wpa_config_write_reg_dword(hk, TEXT("bss_max_count"),
|
||||
config->bss_max_count,
|
||||
DEFAULT_BSS_MAX_COUNT);
|
||||
wpa_config_write_reg_dword(hk, TEXT("filter_ssids"),
|
||||
config->filter_ssids, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -204,6 +204,39 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
|
||||
}
|
||||
|
||||
|
||||
static struct wpa_driver_scan_filter *
|
||||
wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
|
||||
{
|
||||
struct wpa_driver_scan_filter *ssids;
|
||||
struct wpa_ssid *ssid;
|
||||
size_t count;
|
||||
|
||||
*num_ssids = 0;
|
||||
if (!conf->filter_ssids)
|
||||
return NULL;
|
||||
|
||||
for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
|
||||
if (ssid->ssid && ssid->ssid_len)
|
||||
count++;
|
||||
}
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter));
|
||||
if (ssids == NULL)
|
||||
return NULL;
|
||||
|
||||
for (ssid = conf->ssid; ssid; ssid = ssid->next) {
|
||||
if (!ssid->ssid || !ssid->ssid_len)
|
||||
continue;
|
||||
os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
|
||||
ssids[*num_ssids].ssid_len = ssid->ssid_len;
|
||||
(*num_ssids)++;
|
||||
}
|
||||
|
||||
return ssids;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
@ -258,7 +291,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 &&
|
||||
!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) &&
|
||||
wps != 2) {
|
||||
wps != 2 && !wpa_s->conf->filter_ssids) {
|
||||
wpa_s->scan_res_tried++;
|
||||
wpa_printf(MSG_DEBUG, "Trying to get current scan results "
|
||||
"first without requesting a new scan to speed up "
|
||||
@ -363,10 +396,14 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
params.filter_ssids = wpa_supplicant_build_filter_ssids(
|
||||
wpa_s->conf, ¶ms.num_filter_ssids);
|
||||
|
||||
ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms);
|
||||
|
||||
wpabuf_free(wps_ie);
|
||||
os_free(params.freqs);
|
||||
os_free(params.filter_ssids);
|
||||
|
||||
if (ret) {
|
||||
wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
|
||||
|
@ -218,6 +218,12 @@ fast_reauth=1
|
||||
#bss_max_count=200
|
||||
|
||||
|
||||
# filter_ssids - SSID-based scan result filtering
|
||||
# 0 = do not filter scan results (default)
|
||||
# 1 = only include configured SSIDs in scan results/BSS table
|
||||
#filter_ssids=0
|
||||
|
||||
|
||||
# network block
|
||||
#
|
||||
# Each network (usually AP's sharing the same SSID) is configured as a separate
|
||||
|
Loading…
Reference in New Issue
Block a user