18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant - Temporary BSSID blacklist
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "blacklist.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_blacklist_get - Get the blacklist entry for a BSSID
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: BSSID
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Matching blacklist entry for the BSSID or %NULL if not found
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *bssid)
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_blacklist *e;
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy	if (wpa_s == NULL || bssid == NULL)
27b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy		return NULL;
28b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = wpa_s->blacklist;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (e) {
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return e;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e = e->next;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_blacklist_add - Add an BSSID to the blacklist
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: BSSID to be added to the blacklist
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Current blacklist count on success, -1 on failure
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds the specified BSSID to the blacklist or increases the
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * blacklist count if the BSSID was already listed. It should be called when
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * an association attempt fails either due to the selected BSS rejecting
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * association or due to timeout.
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This blacklist is used to force %wpa_supplicant to go through all available
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * BSSes before retrying to associate with an BSS that rejected or timed out
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * association. It does not prevent the listed BSS from being used; it only
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * changes the order in which they are tried.
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_blacklist *e;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
60b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy	if (wpa_s == NULL || bssid == NULL)
61b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy		return -1;
62b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = wpa_blacklist_get(wpa_s, bssid);
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e) {
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->count++;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count "
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "incremented to %d",
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(bssid), e->count);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return e->count;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = os_zalloc(sizeof(*e));
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e == NULL)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(e->bssid, bssid, ETH_ALEN);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->count = 1;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->next = wpa_s->blacklist;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->blacklist = e;
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into blacklist",
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(bssid));
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return e->count;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_blacklist_del - Remove an BSSID from the blacklist
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: BSSID to be removed from the blacklist
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_blacklist *e, *prev = NULL;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
96b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy	if (wpa_s == NULL || bssid == NULL)
97b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy		return -1;
98b8fdecbfd0a0cdbbb17b902a6be87c84227b9b11Sasha Levitskiy
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = wpa_s->blacklist;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (e) {
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev == NULL) {
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s->blacklist = e->next;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = e->next;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "blacklist", MAC2STR(bssid));
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(e);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = e;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e = e->next;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_blacklist_clear - Clear the blacklist of all entries
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_blacklist *e, *prev;
126d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int max_count = 0;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = wpa_s->blacklist;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->blacklist = NULL;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (e) {
131d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (e->count > max_count)
132d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			max_count = e->count;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = e;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e = e->next;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "blacklist (clear)", MAC2STR(prev->bssid));
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
139d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
140d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_s->extra_blacklist_count += max_count;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
142