Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * BSS table
      3  * Copyright (c) 2009-2010, 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 "utils/includes.h"
     10 
     11 #include "utils/common.h"
     12 #include "utils/eloop.h"
     13 #include "common/ieee802_11_defs.h"
     14 #include "drivers/driver.h"
     15 #include "wpa_supplicant_i.h"
     16 #include "config.h"
     17 #include "notify.h"
     18 #include "scan.h"
     19 #include "bss.h"
     20 
     21 
     22 /**
     23  * WPA_BSS_EXPIRATION_PERIOD - Period of expiration run in seconds
     24  */
     25 #define WPA_BSS_EXPIRATION_PERIOD 10
     26 
     27 #define WPA_BSS_FREQ_CHANGED_FLAG	BIT(0)
     28 #define WPA_BSS_SIGNAL_CHANGED_FLAG	BIT(1)
     29 #define WPA_BSS_PRIVACY_CHANGED_FLAG	BIT(2)
     30 #define WPA_BSS_MODE_CHANGED_FLAG	BIT(3)
     31 #define WPA_BSS_WPAIE_CHANGED_FLAG	BIT(4)
     32 #define WPA_BSS_RSNIE_CHANGED_FLAG	BIT(5)
     33 #define WPA_BSS_WPS_CHANGED_FLAG	BIT(6)
     34 #define WPA_BSS_RATES_CHANGED_FLAG	BIT(7)
     35 #define WPA_BSS_IES_CHANGED_FLAG	BIT(8)
     36 
     37 
     38 static void wpa_bss_set_hessid(struct wpa_bss *bss)
     39 {
     40 #ifdef CONFIG_INTERWORKING
     41 	const u8 *ie = wpa_bss_get_ie(bss, WLAN_EID_INTERWORKING);
     42 	if (ie == NULL || (ie[1] != 7 && ie[1] != 9)) {
     43 		os_memset(bss->hessid, 0, ETH_ALEN);
     44 		return;
     45 	}
     46 	if (ie[1] == 7)
     47 		os_memcpy(bss->hessid, ie + 3, ETH_ALEN);
     48 	else
     49 		os_memcpy(bss->hessid, ie + 5, ETH_ALEN);
     50 #endif /* CONFIG_INTERWORKING */
     51 }
     52 
     53 
     54 struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
     55 {
     56 	struct wpa_bss_anqp *anqp;
     57 	anqp = os_zalloc(sizeof(*anqp));
     58 	if (anqp == NULL)
     59 		return NULL;
     60 	anqp->users = 1;
     61 	return anqp;
     62 }
     63 
     64 
     65 static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
     66 {
     67 	if (anqp == NULL)
     68 		return;
     69 
     70 	anqp->users--;
     71 	if (anqp->users > 0) {
     72 		/* Another BSS entry holds a pointer to this ANQP info */
     73 		return;
     74 	}
     75 
     76 #ifdef CONFIG_INTERWORKING
     77 	wpabuf_free(anqp->venue_name);
     78 	wpabuf_free(anqp->network_auth_type);
     79 	wpabuf_free(anqp->roaming_consortium);
     80 	wpabuf_free(anqp->ip_addr_type_availability);
     81 	wpabuf_free(anqp->nai_realm);
     82 	wpabuf_free(anqp->anqp_3gpp);
     83 	wpabuf_free(anqp->domain_name);
     84 #endif /* CONFIG_INTERWORKING */
     85 #ifdef CONFIG_HS20
     86 	wpabuf_free(anqp->hs20_operator_friendly_name);
     87 	wpabuf_free(anqp->hs20_wan_metrics);
     88 	wpabuf_free(anqp->hs20_connection_capability);
     89 	wpabuf_free(anqp->hs20_operating_class);
     90 #endif /* CONFIG_HS20 */
     91 
     92 	os_free(anqp);
     93 }
     94 
     95 
     96 static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
     97 			   const char *reason)
     98 {
     99 	if (wpa_s->last_scan_res) {
    100 		unsigned int i;
    101 		for (i = 0; i < wpa_s->last_scan_res_used; i++) {
    102 			if (wpa_s->last_scan_res[i] == bss) {
    103 				os_memmove(&wpa_s->last_scan_res[i],
    104 					   &wpa_s->last_scan_res[i + 1],
    105 					   (wpa_s->last_scan_res_used - i - 1)
    106 					   * sizeof(struct wpa_bss *));
    107 				wpa_s->last_scan_res_used--;
    108 				break;
    109 			}
    110 		}
    111 	}
    112 	dl_list_del(&bss->list);
    113 	dl_list_del(&bss->list_id);
    114 	wpa_s->num_bss--;
    115 	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR
    116 		" SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid),
    117 		wpa_ssid_txt(bss->ssid, bss->ssid_len), reason);
    118 	wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id);
    119 	wpa_bss_anqp_free(bss->anqp);
    120 	os_free(bss);
    121 }
    122 
    123 
    124 struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
    125 			     const u8 *ssid, size_t ssid_len)
    126 {
    127 	struct wpa_bss *bss;
    128 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
    129 		return NULL;
    130 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    131 		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
    132 		    bss->ssid_len == ssid_len &&
    133 		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
    134 			return bss;
    135 	}
    136 	return NULL;
    137 }
    138 
    139 
    140 static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src)
    141 {
    142 	os_time_t usec;
    143 
    144 	dst->flags = src->flags;
    145 	os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
    146 	dst->freq = src->freq;
    147 	dst->beacon_int = src->beacon_int;
    148 	dst->caps = src->caps;
    149 	dst->qual = src->qual;
    150 	dst->noise = src->noise;
    151 	dst->level = src->level;
    152 	dst->tsf = src->tsf;
    153 
    154 	os_get_time(&dst->last_update);
    155 	dst->last_update.sec -= src->age / 1000;
    156 	usec = (src->age % 1000) * 1000;
    157 	if (dst->last_update.usec < usec) {
    158 		dst->last_update.sec--;
    159 		dst->last_update.usec += 1000000;
    160 	}
    161 	dst->last_update.usec -= usec;
    162 }
    163 
    164 
    165 static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
    166 {
    167 	struct wpa_ssid *ssid;
    168 
    169 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    170 		if (ssid->ssid == NULL || ssid->ssid_len == 0)
    171 			continue;
    172 		if (ssid->ssid_len == bss->ssid_len &&
    173 		    os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) == 0)
    174 			return 1;
    175 	}
    176 
    177 	return 0;
    178 }
    179 
    180 
    181 static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
    182 {
    183 	return bss == wpa_s->current_bss ||
    184 		os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
    185 		os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0;
    186 }
    187 
    188 
    189 static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s)
    190 {
    191 	struct wpa_bss *bss;
    192 
    193 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    194 		if (!wpa_bss_known(wpa_s, bss)) {
    195 			wpa_bss_remove(wpa_s, bss, __func__);
    196 			return 0;
    197 		}
    198 	}
    199 
    200 	return -1;
    201 }
    202 
    203 
    204 static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s)
    205 {
    206 	struct wpa_bss *bss;
    207 
    208 	/*
    209 	 * Remove the oldest entry that does not match with any configured
    210 	 * network.
    211 	 */
    212 	if (wpa_bss_remove_oldest_unknown(wpa_s) == 0)
    213 		return 0;
    214 
    215 	/*
    216 	 * Remove the oldest entry that isn't currently in use.
    217 	 */
    218 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    219 		if (!wpa_bss_in_use(wpa_s, bss)) {
    220 			wpa_bss_remove(wpa_s, bss, __func__);
    221 			return 0;
    222 		}
    223 	}
    224 
    225 	return -1;
    226 }
    227 
    228 
    229 static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
    230 				    const u8 *ssid, size_t ssid_len,
    231 				    struct wpa_scan_res *res)
    232 {
    233 	struct wpa_bss *bss;
    234 
    235 	bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
    236 	if (bss == NULL)
    237 		return NULL;
    238 	bss->id = wpa_s->bss_next_id++;
    239 	bss->last_update_idx = wpa_s->bss_update_idx;
    240 	wpa_bss_copy_res(bss, res);
    241 	os_memcpy(bss->ssid, ssid, ssid_len);
    242 	bss->ssid_len = ssid_len;
    243 	bss->ie_len = res->ie_len;
    244 	bss->beacon_ie_len = res->beacon_ie_len;
    245 	os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
    246 	wpa_bss_set_hessid(bss);
    247 
    248 	dl_list_add_tail(&wpa_s->bss, &bss->list);
    249 	dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
    250 	wpa_s->num_bss++;
    251 	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
    252 		" SSID '%s'",
    253 		bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len));
    254 	wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
    255 	if (wpa_s->num_bss > wpa_s->conf->bss_max_count &&
    256 	    wpa_bss_remove_oldest(wpa_s) != 0) {
    257 		wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d "
    258 			   "because all BSSes are in use. We should normally "
    259 			   "not get here!", (int) wpa_s->num_bss);
    260 		wpa_s->conf->bss_max_count = wpa_s->num_bss;
    261 	}
    262 	return bss;
    263 }
    264 
    265 
    266 static int are_ies_equal(const struct wpa_bss *old,
    267 			 const struct wpa_scan_res *new, u32 ie)
    268 {
    269 	const u8 *old_ie, *new_ie;
    270 	struct wpabuf *old_ie_buff = NULL;
    271 	struct wpabuf *new_ie_buff = NULL;
    272 	int new_ie_len, old_ie_len, ret, is_multi;
    273 
    274 	switch (ie) {
    275 	case WPA_IE_VENDOR_TYPE:
    276 		old_ie = wpa_bss_get_vendor_ie(old, ie);
    277 		new_ie = wpa_scan_get_vendor_ie(new, ie);
    278 		is_multi = 0;
    279 		break;
    280 	case WPS_IE_VENDOR_TYPE:
    281 		old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie);
    282 		new_ie_buff = wpa_scan_get_vendor_ie_multi(new, ie);
    283 		is_multi = 1;
    284 		break;
    285 	case WLAN_EID_RSN:
    286 	case WLAN_EID_SUPP_RATES:
    287 	case WLAN_EID_EXT_SUPP_RATES:
    288 		old_ie = wpa_bss_get_ie(old, ie);
    289 		new_ie = wpa_scan_get_ie(new, ie);
    290 		is_multi = 0;
    291 		break;
    292 	default:
    293 		wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__);
    294 		return 0;
    295 	}
    296 
    297 	if (is_multi) {
    298 		/* in case of multiple IEs stored in buffer */
    299 		old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL;
    300 		new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL;
    301 		old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0;
    302 		new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0;
    303 	} else {
    304 		/* in case of single IE */
    305 		old_ie_len = old_ie ? old_ie[1] + 2 : 0;
    306 		new_ie_len = new_ie ? new_ie[1] + 2 : 0;
    307 	}
    308 
    309 	if (!old_ie || !new_ie)
    310 		ret = !old_ie && !new_ie;
    311 	else
    312 		ret = (old_ie_len == new_ie_len &&
    313 		       os_memcmp(old_ie, new_ie, old_ie_len) == 0);
    314 
    315 	wpabuf_free(old_ie_buff);
    316 	wpabuf_free(new_ie_buff);
    317 
    318 	return ret;
    319 }
    320 
    321 
    322 static u32 wpa_bss_compare_res(const struct wpa_bss *old,
    323 			       const struct wpa_scan_res *new)
    324 {
    325 	u32 changes = 0;
    326 	int caps_diff = old->caps ^ new->caps;
    327 
    328 	if (old->freq != new->freq)
    329 		changes |= WPA_BSS_FREQ_CHANGED_FLAG;
    330 
    331 	if (old->level != new->level)
    332 		changes |= WPA_BSS_SIGNAL_CHANGED_FLAG;
    333 
    334 	if (caps_diff & IEEE80211_CAP_PRIVACY)
    335 		changes |= WPA_BSS_PRIVACY_CHANGED_FLAG;
    336 
    337 	if (caps_diff & IEEE80211_CAP_IBSS)
    338 		changes |= WPA_BSS_MODE_CHANGED_FLAG;
    339 
    340 	if (old->ie_len == new->ie_len &&
    341 	    os_memcmp(old + 1, new + 1, old->ie_len) == 0)
    342 		return changes;
    343 	changes |= WPA_BSS_IES_CHANGED_FLAG;
    344 
    345 	if (!are_ies_equal(old, new, WPA_IE_VENDOR_TYPE))
    346 		changes |= WPA_BSS_WPAIE_CHANGED_FLAG;
    347 
    348 	if (!are_ies_equal(old, new, WLAN_EID_RSN))
    349 		changes |= WPA_BSS_RSNIE_CHANGED_FLAG;
    350 
    351 	if (!are_ies_equal(old, new, WPS_IE_VENDOR_TYPE))
    352 		changes |= WPA_BSS_WPS_CHANGED_FLAG;
    353 
    354 	if (!are_ies_equal(old, new, WLAN_EID_SUPP_RATES) ||
    355 	    !are_ies_equal(old, new, WLAN_EID_EXT_SUPP_RATES))
    356 		changes |= WPA_BSS_RATES_CHANGED_FLAG;
    357 
    358 	return changes;
    359 }
    360 
    361 
    362 static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
    363 			       const struct wpa_bss *bss)
    364 {
    365 	if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
    366 		wpas_notify_bss_freq_changed(wpa_s, bss->id);
    367 
    368 	if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG)
    369 		wpas_notify_bss_signal_changed(wpa_s, bss->id);
    370 
    371 	if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG)
    372 		wpas_notify_bss_privacy_changed(wpa_s, bss->id);
    373 
    374 	if (changes & WPA_BSS_MODE_CHANGED_FLAG)
    375 		wpas_notify_bss_mode_changed(wpa_s, bss->id);
    376 
    377 	if (changes & WPA_BSS_WPAIE_CHANGED_FLAG)
    378 		wpas_notify_bss_wpaie_changed(wpa_s, bss->id);
    379 
    380 	if (changes & WPA_BSS_RSNIE_CHANGED_FLAG)
    381 		wpas_notify_bss_rsnie_changed(wpa_s, bss->id);
    382 
    383 	if (changes & WPA_BSS_WPS_CHANGED_FLAG)
    384 		wpas_notify_bss_wps_changed(wpa_s, bss->id);
    385 
    386 	if (changes & WPA_BSS_IES_CHANGED_FLAG)
    387 		wpas_notify_bss_ies_changed(wpa_s, bss->id);
    388 
    389 	if (changes & WPA_BSS_RATES_CHANGED_FLAG)
    390 		wpas_notify_bss_rates_changed(wpa_s, bss->id);
    391 }
    392 
    393 
    394 static struct wpa_bss *
    395 wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
    396 	       struct wpa_scan_res *res)
    397 {
    398 	u32 changes;
    399 
    400 	changes = wpa_bss_compare_res(bss, res);
    401 	bss->scan_miss_count = 0;
    402 	bss->last_update_idx = wpa_s->bss_update_idx;
    403 	wpa_bss_copy_res(bss, res);
    404 	/* Move the entry to the end of the list */
    405 	dl_list_del(&bss->list);
    406 	if (bss->ie_len + bss->beacon_ie_len >=
    407 	    res->ie_len + res->beacon_ie_len) {
    408 		os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
    409 		bss->ie_len = res->ie_len;
    410 		bss->beacon_ie_len = res->beacon_ie_len;
    411 	} else {
    412 		struct wpa_bss *nbss;
    413 		struct dl_list *prev = bss->list_id.prev;
    414 		dl_list_del(&bss->list_id);
    415 		nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
    416 				  res->beacon_ie_len);
    417 		if (nbss) {
    418 			unsigned int i;
    419 			for (i = 0; i < wpa_s->last_scan_res_used; i++) {
    420 				if (wpa_s->last_scan_res[i] == bss) {
    421 					wpa_s->last_scan_res[i] = nbss;
    422 					break;
    423 				}
    424 			}
    425 			if (wpa_s->current_bss == bss)
    426 				wpa_s->current_bss = nbss;
    427 			bss = nbss;
    428 			os_memcpy(bss + 1, res + 1,
    429 				  res->ie_len + res->beacon_ie_len);
    430 			bss->ie_len = res->ie_len;
    431 			bss->beacon_ie_len = res->beacon_ie_len;
    432 		}
    433 		dl_list_add(prev, &bss->list_id);
    434 	}
    435 	if (changes & WPA_BSS_IES_CHANGED_FLAG)
    436 		wpa_bss_set_hessid(bss);
    437 	dl_list_add_tail(&wpa_s->bss, &bss->list);
    438 
    439 	notify_bss_changes(wpa_s, changes, bss);
    440 
    441 	return bss;
    442 }
    443 
    444 
    445 void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
    446 {
    447 	wpa_s->bss_update_idx++;
    448 	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
    449 		wpa_s->bss_update_idx);
    450 	wpa_s->last_scan_res_used = 0;
    451 }
    452 
    453 
    454 void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
    455 			     struct wpa_scan_res *res)
    456 {
    457 	const u8 *ssid, *p2p;
    458 	struct wpa_bss *bss;
    459 
    460 	ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
    461 	if (ssid == NULL) {
    462 		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
    463 			MACSTR, MAC2STR(res->bssid));
    464 		return;
    465 	}
    466 	if (ssid[1] > 32) {
    467 		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for "
    468 			MACSTR, MAC2STR(res->bssid));
    469 		return;
    470 	}
    471 
    472 	p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE);
    473 #ifdef CONFIG_P2P
    474 	if (p2p == NULL &&
    475 	    wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
    476 		/*
    477 		 * If it's a P2P specific interface, then don't update
    478 		 * the scan result without a P2P IE.
    479 		 */
    480 		wpa_printf(MSG_DEBUG, "BSS: No P2P IE - skipping BSS " MACSTR
    481 			   " update for P2P interface", MAC2STR(res->bssid));
    482 		return;
    483 	}
    484 #endif /* CONFIG_P2P */
    485 	if (p2p && ssid[1] == P2P_WILDCARD_SSID_LEN &&
    486 	    os_memcmp(ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0)
    487 		return; /* Skip P2P listen discovery results here */
    488 
    489 	/* TODO: add option for ignoring BSSes we are not interested in
    490 	 * (to save memory) */
    491 	bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
    492 	if (bss == NULL)
    493 		bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res);
    494 	else
    495 		bss = wpa_bss_update(wpa_s, bss, res);
    496 
    497 	if (bss == NULL)
    498 		return;
    499 	if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
    500 		struct wpa_bss **n;
    501 		unsigned int siz;
    502 		if (wpa_s->last_scan_res_size == 0)
    503 			siz = 32;
    504 		else
    505 			siz = wpa_s->last_scan_res_size * 2;
    506 		n = os_realloc_array(wpa_s->last_scan_res, siz,
    507 				     sizeof(struct wpa_bss *));
    508 		if (n == NULL)
    509 			return;
    510 		wpa_s->last_scan_res = n;
    511 		wpa_s->last_scan_res_size = siz;
    512 	}
    513 
    514 	wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
    515 }
    516 
    517 
    518 static int wpa_bss_included_in_scan(const struct wpa_bss *bss,
    519 				    const struct scan_info *info)
    520 {
    521 	int found;
    522 	size_t i;
    523 
    524 	if (info == NULL)
    525 		return 1;
    526 
    527 	if (info->num_freqs) {
    528 		found = 0;
    529 		for (i = 0; i < info->num_freqs; i++) {
    530 			if (bss->freq == info->freqs[i]) {
    531 				found = 1;
    532 				break;
    533 			}
    534 		}
    535 		if (!found)
    536 			return 0;
    537 	}
    538 
    539 	if (info->num_ssids) {
    540 		found = 0;
    541 		for (i = 0; i < info->num_ssids; i++) {
    542 			const struct wpa_driver_scan_ssid *s = &info->ssids[i];
    543 			if ((s->ssid == NULL || s->ssid_len == 0) ||
    544 			    (s->ssid_len == bss->ssid_len &&
    545 			     os_memcmp(s->ssid, bss->ssid, bss->ssid_len) ==
    546 			     0)) {
    547 				found = 1;
    548 				break;
    549 			}
    550 		}
    551 		if (!found)
    552 			return 0;
    553 	}
    554 
    555 	return 1;
    556 }
    557 
    558 
    559 void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
    560 			int new_scan)
    561 {
    562 	struct wpa_bss *bss, *n;
    563 
    564 	wpa_s->last_scan_full = 0;
    565 	os_get_time(&wpa_s->last_scan);
    566 	if (!new_scan)
    567 		return; /* do not expire entries without new scan */
    568 
    569 	if (info && !info->aborted && !info->freqs) {
    570 		size_t i;
    571 		if (info->num_ssids == 0) {
    572 			wpa_s->last_scan_full = 1;
    573 		} else {
    574 			for (i = 0; i < info->num_ssids; i++) {
    575 				if (info->ssids[i].ssid == NULL ||
    576 				    info->ssids[i].ssid_len == 0) {
    577 					wpa_s->last_scan_full = 1;
    578 					break;
    579 				}
    580 			}
    581 		}
    582 	}
    583 
    584 	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
    585 		if (wpa_bss_in_use(wpa_s, bss))
    586 			continue;
    587 		if (!wpa_bss_included_in_scan(bss, info))
    588 			continue; /* expire only BSSes that were scanned */
    589 		if (bss->last_update_idx < wpa_s->bss_update_idx)
    590 			bss->scan_miss_count++;
    591 		if (bss->scan_miss_count >=
    592 		    wpa_s->conf->bss_expiration_scan_count) {
    593 			wpa_bss_remove(wpa_s, bss, "no match in scan");
    594 		}
    595 	}
    596 
    597 	wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u "
    598 		   "last_scan_full=%d",
    599 		   wpa_s->last_scan_res_used, wpa_s->last_scan_res_size,
    600 		   wpa_s->last_scan_full);
    601 }
    602 
    603 
    604 void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age)
    605 {
    606 	struct wpa_bss *bss, *n;
    607 	struct os_time t;
    608 
    609 	if (dl_list_empty(&wpa_s->bss))
    610 		return;
    611 
    612 	os_get_time(&t);
    613 	t.sec -= age;
    614 
    615 	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
    616 		if (wpa_bss_in_use(wpa_s, bss))
    617 			continue;
    618 
    619 		if (os_time_before(&bss->last_update, &t)) {
    620 			wpa_bss_remove(wpa_s, bss, __func__);
    621 		} else
    622 			break;
    623 	}
    624 }
    625 
    626 
    627 static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx)
    628 {
    629 	struct wpa_supplicant *wpa_s = eloop_ctx;
    630 
    631 	wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
    632 	eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0,
    633 			       wpa_bss_timeout, wpa_s, NULL);
    634 }
    635 
    636 
    637 int wpa_bss_init(struct wpa_supplicant *wpa_s)
    638 {
    639 	dl_list_init(&wpa_s->bss);
    640 	dl_list_init(&wpa_s->bss_id);
    641 	eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0,
    642 			       wpa_bss_timeout, wpa_s, NULL);
    643 	return 0;
    644 }
    645 
    646 
    647 void wpa_bss_flush(struct wpa_supplicant *wpa_s)
    648 {
    649 	struct wpa_bss *bss, *n;
    650 
    651 	if (wpa_s->bss.next == NULL)
    652 		return; /* BSS table not yet initialized */
    653 
    654 	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
    655 		if (wpa_bss_in_use(wpa_s, bss))
    656 			continue;
    657 		wpa_bss_remove(wpa_s, bss, __func__);
    658 	}
    659 }
    660 
    661 
    662 void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
    663 {
    664 	eloop_cancel_timeout(wpa_bss_timeout, wpa_s, NULL);
    665 	wpa_bss_flush(wpa_s);
    666 }
    667 
    668 
    669 struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
    670 				   const u8 *bssid)
    671 {
    672 	struct wpa_bss *bss;
    673 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
    674 		return NULL;
    675 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
    676 		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
    677 			return bss;
    678 	}
    679 	return NULL;
    680 }
    681 
    682 
    683 #ifdef CONFIG_P2P
    684 struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
    685 					  const u8 *dev_addr)
    686 {
    687 	struct wpa_bss *bss;
    688 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
    689 		u8 addr[ETH_ALEN];
    690 		if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len,
    691 				       addr) == 0 &&
    692 		    os_memcmp(addr, dev_addr, ETH_ALEN) == 0)
    693 			return bss;
    694 	}
    695 	return NULL;
    696 }
    697 #endif /* CONFIG_P2P */
    698 
    699 
    700 struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
    701 {
    702 	struct wpa_bss *bss;
    703 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    704 		if (bss->id == id)
    705 			return bss;
    706 	}
    707 	return NULL;
    708 }
    709 
    710 
    711 const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
    712 {
    713 	const u8 *end, *pos;
    714 
    715 	pos = (const u8 *) (bss + 1);
    716 	end = pos + bss->ie_len;
    717 
    718 	while (pos + 1 < end) {
    719 		if (pos + 2 + pos[1] > end)
    720 			break;
    721 		if (pos[0] == ie)
    722 			return pos;
    723 		pos += 2 + pos[1];
    724 	}
    725 
    726 	return NULL;
    727 }
    728 
    729 
    730 const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
    731 {
    732 	const u8 *end, *pos;
    733 
    734 	pos = (const u8 *) (bss + 1);
    735 	end = pos + bss->ie_len;
    736 
    737 	while (pos + 1 < end) {
    738 		if (pos + 2 + pos[1] > end)
    739 			break;
    740 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    741 		    vendor_type == WPA_GET_BE32(&pos[2]))
    742 			return pos;
    743 		pos += 2 + pos[1];
    744 	}
    745 
    746 	return NULL;
    747 }
    748 
    749 
    750 struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
    751 					    u32 vendor_type)
    752 {
    753 	struct wpabuf *buf;
    754 	const u8 *end, *pos;
    755 
    756 	buf = wpabuf_alloc(bss->ie_len);
    757 	if (buf == NULL)
    758 		return NULL;
    759 
    760 	pos = (const u8 *) (bss + 1);
    761 	end = pos + bss->ie_len;
    762 
    763 	while (pos + 1 < end) {
    764 		if (pos + 2 + pos[1] > end)
    765 			break;
    766 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    767 		    vendor_type == WPA_GET_BE32(&pos[2]))
    768 			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
    769 		pos += 2 + pos[1];
    770 	}
    771 
    772 	if (wpabuf_len(buf) == 0) {
    773 		wpabuf_free(buf);
    774 		buf = NULL;
    775 	}
    776 
    777 	return buf;
    778 }
    779 
    780 
    781 struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
    782 						   u32 vendor_type)
    783 {
    784 	struct wpabuf *buf;
    785 	const u8 *end, *pos;
    786 
    787 	buf = wpabuf_alloc(bss->beacon_ie_len);
    788 	if (buf == NULL)
    789 		return NULL;
    790 
    791 	pos = (const u8 *) (bss + 1);
    792 	pos += bss->ie_len;
    793 	end = pos + bss->beacon_ie_len;
    794 
    795 	while (pos + 1 < end) {
    796 		if (pos + 2 + pos[1] > end)
    797 			break;
    798 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    799 		    vendor_type == WPA_GET_BE32(&pos[2]))
    800 			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
    801 		pos += 2 + pos[1];
    802 	}
    803 
    804 	if (wpabuf_len(buf) == 0) {
    805 		wpabuf_free(buf);
    806 		buf = NULL;
    807 	}
    808 
    809 	return buf;
    810 }
    811 
    812 
    813 int wpa_bss_get_max_rate(const struct wpa_bss *bss)
    814 {
    815 	int rate = 0;
    816 	const u8 *ie;
    817 	int i;
    818 
    819 	ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
    820 	for (i = 0; ie && i < ie[1]; i++) {
    821 		if ((ie[i + 2] & 0x7f) > rate)
    822 			rate = ie[i + 2] & 0x7f;
    823 	}
    824 
    825 	ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
    826 	for (i = 0; ie && i < ie[1]; i++) {
    827 		if ((ie[i + 2] & 0x7f) > rate)
    828 			rate = ie[i + 2] & 0x7f;
    829 	}
    830 
    831 	return rate;
    832 }
    833 
    834 
    835 int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
    836 {
    837 	const u8 *ie, *ie2;
    838 	int i, j;
    839 	unsigned int len;
    840 	u8 *r;
    841 
    842 	ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
    843 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
    844 
    845 	len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0);
    846 
    847 	r = os_malloc(len);
    848 	if (!r)
    849 		return -1;
    850 
    851 	for (i = 0; ie && i < ie[1]; i++)
    852 		r[i] = ie[i + 2] & 0x7f;
    853 
    854 	for (j = 0; ie2 && j < ie2[1]; j++)
    855 		r[i + j] = ie2[j + 2] & 0x7f;
    856 
    857 	*rates = r;
    858 	return len;
    859 }
    860