aboutsummaryrefslogtreecommitdiff
path: root/wpa_supplicant/bssid_ignore.c
diff options
context:
space:
mode:
Diffstat (limited to 'wpa_supplicant/bssid_ignore.c')
-rw-r--r--wpa_supplicant/bssid_ignore.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/wpa_supplicant/bssid_ignore.c b/wpa_supplicant/bssid_ignore.c
new file mode 100644
index 000000000000..e37857798a02
--- /dev/null
+++ b/wpa_supplicant/bssid_ignore.c
@@ -0,0 +1,221 @@
+/*
+ * 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;
+ }
+ }
+}