1189251Ssam/*
2189251Ssam * wpa_supplicant - Temporary BSSID blacklist
3189251Ssam * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam */
8189251Ssam
9189251Ssam#include "includes.h"
10189251Ssam
11189251Ssam#include "common.h"
12189251Ssam#include "wpa_supplicant_i.h"
13189251Ssam#include "blacklist.h"
14189251Ssam
15189251Ssam/**
16189251Ssam * wpa_blacklist_get - Get the blacklist entry for a BSSID
17189251Ssam * @wpa_s: Pointer to wpa_supplicant data
18189251Ssam * @bssid: BSSID
19189251Ssam * Returns: Matching blacklist entry for the BSSID or %NULL if not found
20189251Ssam */
21189251Ssamstruct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
22189251Ssam					 const u8 *bssid)
23189251Ssam{
24189251Ssam	struct wpa_blacklist *e;
25189251Ssam
26252726Srpaulo	if (wpa_s == NULL || bssid == NULL)
27252726Srpaulo		return NULL;
28252726Srpaulo
29189251Ssam	e = wpa_s->blacklist;
30189251Ssam	while (e) {
31189251Ssam		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
32189251Ssam			return e;
33189251Ssam		e = e->next;
34189251Ssam	}
35189251Ssam
36189251Ssam	return NULL;
37189251Ssam}
38189251Ssam
39189251Ssam
40189251Ssam/**
41189251Ssam * wpa_blacklist_add - Add an BSSID to the blacklist
42189251Ssam * @wpa_s: Pointer to wpa_supplicant data
43189251Ssam * @bssid: BSSID to be added to the blacklist
44252726Srpaulo * Returns: Current blacklist count on success, -1 on failure
45189251Ssam *
46189251Ssam * This function adds the specified BSSID to the blacklist or increases the
47189251Ssam * blacklist count if the BSSID was already listed. It should be called when
48189251Ssam * an association attempt fails either due to the selected BSS rejecting
49189251Ssam * association or due to timeout.
50189251Ssam *
51189251Ssam * This blacklist is used to force %wpa_supplicant to go through all available
52189251Ssam * BSSes before retrying to associate with an BSS that rejected or timed out
53189251Ssam * association. It does not prevent the listed BSS from being used; it only
54189251Ssam * changes the order in which they are tried.
55189251Ssam */
56189251Ssamint wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
57189251Ssam{
58189251Ssam	struct wpa_blacklist *e;
59189251Ssam
60252726Srpaulo	if (wpa_s == NULL || bssid == NULL)
61252726Srpaulo		return -1;
62252726Srpaulo
63189251Ssam	e = wpa_blacklist_get(wpa_s, bssid);
64189251Ssam	if (e) {
65189251Ssam		e->count++;
66189251Ssam		wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count "
67189251Ssam			   "incremented to %d",
68189251Ssam			   MAC2STR(bssid), e->count);
69252726Srpaulo		return e->count;
70189251Ssam	}
71189251Ssam
72189251Ssam	e = os_zalloc(sizeof(*e));
73189251Ssam	if (e == NULL)
74189251Ssam		return -1;
75189251Ssam	os_memcpy(e->bssid, bssid, ETH_ALEN);
76189251Ssam	e->count = 1;
77189251Ssam	e->next = wpa_s->blacklist;
78189251Ssam	wpa_s->blacklist = e;
79189251Ssam	wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into blacklist",
80189251Ssam		   MAC2STR(bssid));
81189251Ssam
82252726Srpaulo	return e->count;
83189251Ssam}
84189251Ssam
85189251Ssam
86189251Ssam/**
87189251Ssam * wpa_blacklist_del - Remove an BSSID from the blacklist
88189251Ssam * @wpa_s: Pointer to wpa_supplicant data
89189251Ssam * @bssid: BSSID to be removed from the blacklist
90189251Ssam * Returns: 0 on success, -1 on failure
91189251Ssam */
92189251Ssamint wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
93189251Ssam{
94189251Ssam	struct wpa_blacklist *e, *prev = NULL;
95189251Ssam
96252726Srpaulo	if (wpa_s == NULL || bssid == NULL)
97252726Srpaulo		return -1;
98252726Srpaulo
99189251Ssam	e = wpa_s->blacklist;
100189251Ssam	while (e) {
101189251Ssam		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
102189251Ssam			if (prev == NULL) {
103189251Ssam				wpa_s->blacklist = e->next;
104189251Ssam			} else {
105189251Ssam				prev->next = e->next;
106189251Ssam			}
107189251Ssam			wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
108189251Ssam				   "blacklist", MAC2STR(bssid));
109189251Ssam			os_free(e);
110189251Ssam			return 0;
111189251Ssam		}
112189251Ssam		prev = e;
113189251Ssam		e = e->next;
114189251Ssam	}
115189251Ssam	return -1;
116189251Ssam}
117189251Ssam
118189251Ssam
119189251Ssam/**
120189251Ssam * wpa_blacklist_clear - Clear the blacklist of all entries
121189251Ssam * @wpa_s: Pointer to wpa_supplicant data
122189251Ssam */
123189251Ssamvoid wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
124189251Ssam{
125189251Ssam	struct wpa_blacklist *e, *prev;
126252726Srpaulo	int max_count = 0;
127189251Ssam
128189251Ssam	e = wpa_s->blacklist;
129189251Ssam	wpa_s->blacklist = NULL;
130189251Ssam	while (e) {
131252726Srpaulo		if (e->count > max_count)
132252726Srpaulo			max_count = e->count;
133189251Ssam		prev = e;
134189251Ssam		e = e->next;
135189251Ssam		wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
136189251Ssam			   "blacklist (clear)", MAC2STR(prev->bssid));
137189251Ssam		os_free(prev);
138189251Ssam	}
139252726Srpaulo
140252726Srpaulo	wpa_s->extra_blacklist_count += max_count;
141189251Ssam}
142