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