Home | History | Annotate | Line # | Download | only in wpa_supplicant
bssid_ignore.c revision 1.1
      1 /*
      2  * wpa_supplicant - List of temporarily ignored BSSIDs
      3  * Copyright (c) 2003-2021, Jouni Malinen <j (at) 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 (ether_addr_equal(e->bssid, bssid))
     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_msg(wpa_s, 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_msg(wpa_s, MSG_INFO, "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 (ether_addr_equal(e->bssid, bssid)) {
    127 			if (prev == NULL) {
    128 				wpa_s->bssid_ignore = e->next;
    129 			} else {
    130 				prev->next = e->next;
    131 			}
    132 			wpa_msg(wpa_s, MSG_INFO, "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_msg(wpa_s, MSG_INFO, "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_msg(wpa_s, 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