222 lines
5.4 KiB
C
222 lines
5.4 KiB
C
|
/*
|
||
|
* wpa_supplicant - List of temporarily ignored BSSIDs
|
||
|
* Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
|
||
|
*
|
||
|
* This software may be distributed under the terms of the BSD license.
|
||
|
* See README for more details.
|
||
|
*/
|
||
|
|
||
|
#include "includes.h"
|
||
|
|
||
|
#include "common.h"
|
||
|
#include "wpa_supplicant_i.h"
|
||
|
#include "bssid_ignore.h"
|
||
|
|
||
|
/**
|
||
|
* wpa_bssid_ignore_get - Get the ignore list entry for a BSSID
|
||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||
|
* @bssid: BSSID
|
||
|
* Returns: Matching entry for the BSSID or %NULL if not found
|
||
|
*/
|
||
|
struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
|
||
|
const u8 *bssid)
|
||
|
{
|
||
|
struct wpa_bssid_ignore *e;
|
||
|
|
||
|
if (wpa_s == NULL || bssid == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
if (wpa_s->current_ssid &&
|
||
|
wpa_s->current_ssid->was_recently_reconfigured) {
|
||
|
wpa_bssid_ignore_clear(wpa_s);
|
||
|
wpa_s->current_ssid->was_recently_reconfigured = false;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
wpa_bssid_ignore_update(wpa_s);
|
||
|
|
||
|
e = wpa_s->bssid_ignore;
|
||
|
while (e) {
|
||
|
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
|
||
|
return e;
|
||
|
e = e->next;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* wpa_bssid_ignore_add - Add an BSSID to the ignore list
|
||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||
|
* @bssid: BSSID to be added to the ignore list
|
||
|
* Returns: Current ignore list count on success, -1 on failure
|
||
|
*
|
||
|
* This function adds the specified BSSID to the ignore list or increases the
|
||
|
* ignore count if the BSSID was already listed. It should be called when
|
||
|
* an association attempt fails either due to the selected BSS rejecting
|
||
|
* association or due to timeout.
|
||
|
*
|
||
|
* This ignore list is used to force %wpa_supplicant to go through all available
|
||
|
* BSSes before retrying to associate with an BSS that rejected or timed out
|
||
|
* association. It does not prevent the listed BSS from being used; it only
|
||
|
* changes the order in which they are tried.
|
||
|
*/
|
||
|
int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
||
|
{
|
||
|
struct wpa_bssid_ignore *e;
|
||
|
struct os_reltime now;
|
||
|
|
||
|
if (wpa_s == NULL || bssid == NULL)
|
||
|
return -1;
|
||
|
|
||
|
e = wpa_bssid_ignore_get(wpa_s, bssid);
|
||
|
os_get_reltime(&now);
|
||
|
if (e) {
|
||
|
e->start = now;
|
||
|
e->count++;
|
||
|
if (e->count > 5)
|
||
|
e->timeout_secs = 1800;
|
||
|
else if (e->count == 5)
|
||
|
e->timeout_secs = 600;
|
||
|
else if (e->count == 4)
|
||
|
e->timeout_secs = 120;
|
||
|
else if (e->count == 3)
|
||
|
e->timeout_secs = 60;
|
||
|
else
|
||
|
e->timeout_secs = 10;
|
||
|
wpa_printf(MSG_INFO, "BSSID " MACSTR
|
||
|
" ignore list count incremented to %d, ignoring for %d seconds",
|
||
|
MAC2STR(bssid), e->count, e->timeout_secs);
|
||
|
return e->count;
|
||
|
}
|
||
|
|
||
|
e = os_zalloc(sizeof(*e));
|
||
|
if (e == NULL)
|
||
|
return -1;
|
||
|
os_memcpy(e->bssid, bssid, ETH_ALEN);
|
||
|
e->count = 1;
|
||
|
e->timeout_secs = 10;
|
||
|
e->start = now;
|
||
|
e->next = wpa_s->bssid_ignore;
|
||
|
wpa_s->bssid_ignore = e;
|
||
|
wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
|
||
|
" into ignore list, ignoring for %d seconds",
|
||
|
MAC2STR(bssid), e->timeout_secs);
|
||
|
|
||
|
return e->count;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* wpa_bssid_ignore_del - Remove an BSSID from the ignore list
|
||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||
|
* @bssid: BSSID to be removed from the ignore list
|
||
|
* Returns: 0 on success, -1 on failure
|
||
|
*/
|
||
|
int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
||
|
{
|
||
|
struct wpa_bssid_ignore *e, *prev = NULL;
|
||
|
|
||
|
if (wpa_s == NULL || bssid == NULL)
|
||
|
return -1;
|
||
|
|
||
|
e = wpa_s->bssid_ignore;
|
||
|
while (e) {
|
||
|
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
|
||
|
if (prev == NULL) {
|
||
|
wpa_s->bssid_ignore = e->next;
|
||
|
} else {
|
||
|
prev->next = e->next;
|
||
|
}
|
||
|
wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
|
||
|
" from ignore list", MAC2STR(bssid));
|
||
|
os_free(e);
|
||
|
return 0;
|
||
|
}
|
||
|
prev = e;
|
||
|
e = e->next;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* wpa_bssid_ignore_is_listed - Check whether a BSSID is ignored temporarily
|
||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||
|
* @bssid: BSSID to be checked
|
||
|
* Returns: count if BSS is currently considered to be ignored, 0 otherwise
|
||
|
*/
|
||
|
int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
||
|
{
|
||
|
struct wpa_bssid_ignore *e;
|
||
|
struct os_reltime now;
|
||
|
|
||
|
e = wpa_bssid_ignore_get(wpa_s, bssid);
|
||
|
if (!e)
|
||
|
return 0;
|
||
|
os_get_reltime(&now);
|
||
|
if (os_reltime_expired(&now, &e->start, e->timeout_secs))
|
||
|
return 0;
|
||
|
return e->count;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* wpa_bssid_ignore_clear - Clear the ignore list of all entries
|
||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||
|
*/
|
||
|
void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s)
|
||
|
{
|
||
|
struct wpa_bssid_ignore *e, *prev;
|
||
|
|
||
|
e = wpa_s->bssid_ignore;
|
||
|
wpa_s->bssid_ignore = NULL;
|
||
|
while (e) {
|
||
|
prev = e;
|
||
|
e = e->next;
|
||
|
wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
|
||
|
" from ignore list (clear)", MAC2STR(prev->bssid));
|
||
|
os_free(prev);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* wpa_bssid_ignore_update - Update the entries in the ignore list,
|
||
|
* deleting entries that have been expired for over an hour.
|
||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||
|
*/
|
||
|
void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s)
|
||
|
{
|
||
|
struct wpa_bssid_ignore *e, *prev = NULL;
|
||
|
struct os_reltime now;
|
||
|
|
||
|
if (!wpa_s)
|
||
|
return;
|
||
|
|
||
|
e = wpa_s->bssid_ignore;
|
||
|
os_get_reltime(&now);
|
||
|
while (e) {
|
||
|
if (os_reltime_expired(&now, &e->start,
|
||
|
e->timeout_secs + 3600)) {
|
||
|
struct wpa_bssid_ignore *to_delete = e;
|
||
|
|
||
|
if (prev) {
|
||
|
prev->next = e->next;
|
||
|
e = prev->next;
|
||
|
} else {
|
||
|
wpa_s->bssid_ignore = e->next;
|
||
|
e = wpa_s->bssid_ignore;
|
||
|
}
|
||
|
wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
|
||
|
" from ignore list (expired)",
|
||
|
MAC2STR(to_delete->bssid));
|
||
|
os_free(to_delete);
|
||
|
} else {
|
||
|
prev = e;
|
||
|
e = e->next;
|
||
|
}
|
||
|
}
|
||
|
}
|