| /* |
| * 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; |
| } |
| } |
| } |