1 /*
2 * wpa_supplicant - List of temporarily ignored BSSIDs
3 * Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "wpa_supplicant_i.h"
13 #include "bssid_ignore.h"
14
15 /**
16 * wpa_bssid_ignore_get - Get the ignore list entry for a BSSID
17 * @wpa_s: Pointer to wpa_supplicant data
18 * @bssid: BSSID
19 * Returns: Matching entry for the BSSID or %NULL if not found
20 */
wpa_bssid_ignore_get(struct wpa_supplicant * wpa_s,const u8 * bssid)21 struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
22 const u8 *bssid)
23 {
24 struct wpa_bssid_ignore *e;
25
26 if (wpa_s == NULL || bssid == NULL)
27 return NULL;
28
29 if (wpa_s->current_ssid &&
30 wpa_s->current_ssid->was_recently_reconfigured) {
31 wpa_bssid_ignore_clear(wpa_s);
32 wpa_s->current_ssid->was_recently_reconfigured = false;
33 return NULL;
34 }
35
36 wpa_bssid_ignore_update(wpa_s);
37
38 e = wpa_s->bssid_ignore;
39 while (e) {
40 if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
41 return e;
42 e = e->next;
43 }
44
45 return NULL;
46 }
47
48
49 /**
50 * wpa_bssid_ignore_add - Add an BSSID to the ignore list
51 * @wpa_s: Pointer to wpa_supplicant data
52 * @bssid: BSSID to be added to the ignore list
53 * Returns: Current ignore list count on success, -1 on failure
54 *
55 * This function adds the specified BSSID to the ignore list or increases the
56 * ignore count if the BSSID was already listed. It should be called when
57 * an association attempt fails either due to the selected BSS rejecting
58 * association or due to timeout.
59 *
60 * This ignore list is used to force %wpa_supplicant to go through all available
61 * BSSes before retrying to associate with an BSS that rejected or timed out
62 * association. It does not prevent the listed BSS from being used; it only
63 * changes the order in which they are tried.
64 */
wpa_bssid_ignore_add(struct wpa_supplicant * wpa_s,const u8 * bssid)65 int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
66 {
67 struct wpa_bssid_ignore *e;
68 struct os_reltime now;
69
70 if (wpa_s == NULL || bssid == NULL)
71 return -1;
72
73 e = wpa_bssid_ignore_get(wpa_s, bssid);
74 os_get_reltime(&now);
75 if (e) {
76 e->start = now;
77 e->count++;
78 if (e->count > 5)
79 e->timeout_secs = 1800;
80 else if (e->count == 5)
81 e->timeout_secs = 600;
82 else if (e->count == 4)
83 e->timeout_secs = 120;
84 else if (e->count == 3)
85 e->timeout_secs = 60;
86 else
87 e->timeout_secs = 10;
88 wpa_printf(MSG_INFO, "BSSID " MACSTR
89 " ignore list count incremented to %d, ignoring for %d seconds",
90 MAC2STR(bssid), e->count, e->timeout_secs);
91 return e->count;
92 }
93
94 e = os_zalloc(sizeof(*e));
95 if (e == NULL)
96 return -1;
97 os_memcpy(e->bssid, bssid, ETH_ALEN);
98 e->count = 1;
99 e->timeout_secs = 10;
100 e->start = now;
101 e->next = wpa_s->bssid_ignore;
102 wpa_s->bssid_ignore = e;
103 wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
104 " into ignore list, ignoring for %d seconds",
105 MAC2STR(bssid), e->timeout_secs);
106
107 return e->count;
108 }
109
110
111 /**
112 * wpa_bssid_ignore_del - Remove an BSSID from the ignore list
113 * @wpa_s: Pointer to wpa_supplicant data
114 * @bssid: BSSID to be removed from the ignore list
115 * Returns: 0 on success, -1 on failure
116 */
wpa_bssid_ignore_del(struct wpa_supplicant * wpa_s,const u8 * bssid)117 int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
118 {
119 struct wpa_bssid_ignore *e, *prev = NULL;
120
121 if (wpa_s == NULL || bssid == NULL)
122 return -1;
123
124 e = wpa_s->bssid_ignore;
125 while (e) {
126 if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
127 if (prev == NULL) {
128 wpa_s->bssid_ignore = e->next;
129 } else {
130 prev->next = e->next;
131 }
132 wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
133 " from ignore list", MAC2STR(bssid));
134 os_free(e);
135 return 0;
136 }
137 prev = e;
138 e = e->next;
139 }
140 return -1;
141 }
142
143
144 /**
145 * wpa_bssid_ignore_is_listed - Check whether a BSSID is ignored temporarily
146 * @wpa_s: Pointer to wpa_supplicant data
147 * @bssid: BSSID to be checked
148 * Returns: count if BSS is currently considered to be ignored, 0 otherwise
149 */
wpa_bssid_ignore_is_listed(struct wpa_supplicant * wpa_s,const u8 * bssid)150 int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid)
151 {
152 struct wpa_bssid_ignore *e;
153 struct os_reltime now;
154
155 e = wpa_bssid_ignore_get(wpa_s, bssid);
156 if (!e)
157 return 0;
158 os_get_reltime(&now);
159 if (os_reltime_expired(&now, &e->start, e->timeout_secs))
160 return 0;
161 return e->count;
162 }
163
164
165 /**
166 * wpa_bssid_ignore_clear - Clear the ignore list of all entries
167 * @wpa_s: Pointer to wpa_supplicant data
168 */
wpa_bssid_ignore_clear(struct wpa_supplicant * wpa_s)169 void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s)
170 {
171 struct wpa_bssid_ignore *e, *prev;
172
173 e = wpa_s->bssid_ignore;
174 wpa_s->bssid_ignore = NULL;
175 while (e) {
176 prev = e;
177 e = e->next;
178 wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
179 " from ignore list (clear)", MAC2STR(prev->bssid));
180 os_free(prev);
181 }
182 }
183
184
185 /**
186 * wpa_bssid_ignore_update - Update the entries in the ignore list,
187 * deleting entries that have been expired for over an hour.
188 * @wpa_s: Pointer to wpa_supplicant data
189 */
wpa_bssid_ignore_update(struct wpa_supplicant * wpa_s)190 void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s)
191 {
192 struct wpa_bssid_ignore *e, *prev = NULL;
193 struct os_reltime now;
194
195 if (!wpa_s)
196 return;
197
198 e = wpa_s->bssid_ignore;
199 os_get_reltime(&now);
200 while (e) {
201 if (os_reltime_expired(&now, &e->start,
202 e->timeout_secs + 3600)) {
203 struct wpa_bssid_ignore *to_delete = e;
204
205 if (prev) {
206 prev->next = e->next;
207 e = prev->next;
208 } else {
209 wpa_s->bssid_ignore = e->next;
210 e = wpa_s->bssid_ignore;
211 }
212 wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
213 " from ignore list (expired)",
214 MAC2STR(to_delete->bssid));
215 os_free(to_delete);
216 } else {
217 prev = e;
218 e = e->next;
219 }
220 }
221 }
222