1 /*
2  * wpa_supplicant - Temporary BSSID blacklist
3  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "wpa_supplicant_i.h"
19 #include "blacklist.h"
20 
21 /**
22  * wpa_blacklist_get - Get the blacklist entry for a BSSID
23  * @wpa_s: Pointer to wpa_supplicant data
24  * @bssid: BSSID
25  * Returns: Matching blacklist entry for the BSSID or %NULL if not found
26  */
27 struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
28 					 const u8 *bssid)
29 {
30 	struct wpa_blacklist *e;
31 
32 	e = wpa_s->blacklist;
33 	while (e) {
34 		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
35 			return e;
36 		e = e->next;
37 	}
38 
39 	return NULL;
40 }
41 
42 
43 /**
44  * wpa_blacklist_add - Add an BSSID to the blacklist
45  * @wpa_s: Pointer to wpa_supplicant data
46  * @bssid: BSSID to be added to the blacklist
47  * Returns: 0 on success, -1 on failure
48  *
49  * This function adds the specified BSSID to the blacklist or increases the
50  * blacklist count if the BSSID was already listed. It should be called when
51  * an association attempt fails either due to the selected BSS rejecting
52  * association or due to timeout.
53  *
54  * This blacklist is used to force %wpa_supplicant to go through all available
55  * BSSes before retrying to associate with an BSS that rejected or timed out
56  * association. It does not prevent the listed BSS from being used; it only
57  * changes the order in which they are tried.
58  */
59 int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
60 {
61 	struct wpa_blacklist *e;
62 
63 	e = wpa_blacklist_get(wpa_s, bssid);
64 	if (e) {
65 		e->count++;
66 		wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count "
67 			   "incremented to %d",
68 			   MAC2STR(bssid), e->count);
69 		return 0;
70 	}
71 
72 	e = os_zalloc(sizeof(*e));
73 	if (e == NULL)
74 		return -1;
75 	os_memcpy(e->bssid, bssid, ETH_ALEN);
76 	e->count = 1;
77 	e->next = wpa_s->blacklist;
78 	wpa_s->blacklist = e;
79 	wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into blacklist",
80 		   MAC2STR(bssid));
81 
82 	return 0;
83 }
84 
85 
86 /**
87  * wpa_blacklist_del - Remove an BSSID from the blacklist
88  * @wpa_s: Pointer to wpa_supplicant data
89  * @bssid: BSSID to be removed from the blacklist
90  * Returns: 0 on success, -1 on failure
91  */
92 int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
93 {
94 	struct wpa_blacklist *e, *prev = NULL;
95 
96 	e = wpa_s->blacklist;
97 	while (e) {
98 		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
99 			if (prev == NULL) {
100 				wpa_s->blacklist = e->next;
101 			} else {
102 				prev->next = e->next;
103 			}
104 			wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
105 				   "blacklist", MAC2STR(bssid));
106 			os_free(e);
107 			return 0;
108 		}
109 		prev = e;
110 		e = e->next;
111 	}
112 	return -1;
113 }
114 
115 
116 /**
117  * wpa_blacklist_clear - Clear the blacklist of all entries
118  * @wpa_s: Pointer to wpa_supplicant data
119  */
120 void wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
121 {
122 	struct wpa_blacklist *e, *prev;
123 
124 	e = wpa_s->blacklist;
125 	wpa_s->blacklist = NULL;
126 	while (e) {
127 		prev = e;
128 		e = e->next;
129 		wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
130 			   "blacklist (clear)", MAC2STR(prev->bssid));
131 		os_free(prev);
132 	}
133 }
134