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