blob: e37857798a0282daaac074d521e27d1f33d4f63b [file] [log] [blame]
/*
* 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;
}
}
}