Home | History | Annotate | Line # | Download | only in wpa_supplicant
bss.c revision 1.1.1.1.8.1
      1 /*
      2  * BSS table
      3  * Copyright (c) 2009-2015, 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 "eap_peer/eap.h"
     16 #include "wpa_supplicant_i.h"
     17 #include "config.h"
     18 #include "notify.h"
     19 #include "scan.h"
     20 #include "bss.h"
     21 
     22 
     23 #define WPA_BSS_FREQ_CHANGED_FLAG	BIT(0)
     24 #define WPA_BSS_SIGNAL_CHANGED_FLAG	BIT(1)
     25 #define WPA_BSS_PRIVACY_CHANGED_FLAG	BIT(2)
     26 #define WPA_BSS_MODE_CHANGED_FLAG	BIT(3)
     27 #define WPA_BSS_WPAIE_CHANGED_FLAG	BIT(4)
     28 #define WPA_BSS_RSNIE_CHANGED_FLAG	BIT(5)
     29 #define WPA_BSS_WPS_CHANGED_FLAG	BIT(6)
     30 #define WPA_BSS_RATES_CHANGED_FLAG	BIT(7)
     31 #define WPA_BSS_IES_CHANGED_FLAG	BIT(8)
     32 
     33 
     34 static void wpa_bss_set_hessid(struct wpa_bss *bss)
     35 {
     36 #ifdef CONFIG_INTERWORKING
     37 	const u8 *ie = wpa_bss_get_ie(bss, WLAN_EID_INTERWORKING);
     38 	if (ie == NULL || (ie[1] != 7 && ie[1] != 9)) {
     39 		os_memset(bss->hessid, 0, ETH_ALEN);
     40 		return;
     41 	}
     42 	if (ie[1] == 7)
     43 		os_memcpy(bss->hessid, ie + 3, ETH_ALEN);
     44 	else
     45 		os_memcpy(bss->hessid, ie + 5, ETH_ALEN);
     46 #endif /* CONFIG_INTERWORKING */
     47 }
     48 
     49 
     50 /**
     51  * wpa_bss_anqp_alloc - Allocate ANQP data structure for a BSS entry
     52  * Returns: Allocated ANQP data structure or %NULL on failure
     53  *
     54  * The allocated ANQP data structure has its users count set to 1. It may be
     55  * shared by multiple BSS entries and each shared entry is freed with
     56  * wpa_bss_anqp_free().
     57  */
     58 struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
     59 {
     60 	struct wpa_bss_anqp *anqp;
     61 	anqp = os_zalloc(sizeof(*anqp));
     62 	if (anqp == NULL)
     63 		return NULL;
     64 #ifdef CONFIG_INTERWORKING
     65 	dl_list_init(&anqp->anqp_elems);
     66 #endif /* CONFIG_INTERWORKING */
     67 	anqp->users = 1;
     68 	return anqp;
     69 }
     70 
     71 
     72 /**
     73  * wpa_bss_anqp_clone - Clone an ANQP data structure
     74  * @anqp: ANQP data structure from wpa_bss_anqp_alloc()
     75  * Returns: Cloned ANQP data structure or %NULL on failure
     76  */
     77 static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
     78 {
     79 	struct wpa_bss_anqp *n;
     80 
     81 	n = os_zalloc(sizeof(*n));
     82 	if (n == NULL)
     83 		return NULL;
     84 
     85 #define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
     86 #ifdef CONFIG_INTERWORKING
     87 	dl_list_init(&n->anqp_elems);
     88 	ANQP_DUP(capability_list);
     89 	ANQP_DUP(venue_name);
     90 	ANQP_DUP(network_auth_type);
     91 	ANQP_DUP(roaming_consortium);
     92 	ANQP_DUP(ip_addr_type_availability);
     93 	ANQP_DUP(nai_realm);
     94 	ANQP_DUP(anqp_3gpp);
     95 	ANQP_DUP(domain_name);
     96 #endif /* CONFIG_INTERWORKING */
     97 #ifdef CONFIG_HS20
     98 	ANQP_DUP(hs20_capability_list);
     99 	ANQP_DUP(hs20_operator_friendly_name);
    100 	ANQP_DUP(hs20_wan_metrics);
    101 	ANQP_DUP(hs20_connection_capability);
    102 	ANQP_DUP(hs20_operating_class);
    103 	ANQP_DUP(hs20_osu_providers_list);
    104 #endif /* CONFIG_HS20 */
    105 #undef ANQP_DUP
    106 
    107 	return n;
    108 }
    109 
    110 
    111 /**
    112  * wpa_bss_anqp_unshare_alloc - Unshare ANQP data (if shared) in a BSS entry
    113  * @bss: BSS entry
    114  * Returns: 0 on success, -1 on failure
    115  *
    116  * This function ensures the specific BSS entry has an ANQP data structure that
    117  * is not shared with any other BSS entry.
    118  */
    119 int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss)
    120 {
    121 	struct wpa_bss_anqp *anqp;
    122 
    123 	if (bss->anqp && bss->anqp->users > 1) {
    124 		/* allocated, but shared - clone an unshared copy */
    125 		anqp = wpa_bss_anqp_clone(bss->anqp);
    126 		if (anqp == NULL)
    127 			return -1;
    128 		anqp->users = 1;
    129 		bss->anqp->users--;
    130 		bss->anqp = anqp;
    131 		return 0;
    132 	}
    133 
    134 	if (bss->anqp)
    135 		return 0; /* already allocated and not shared */
    136 
    137 	/* not allocated - allocate a new storage area */
    138 	bss->anqp = wpa_bss_anqp_alloc();
    139 	return bss->anqp ? 0 : -1;
    140 }
    141 
    142 
    143 /**
    144  * wpa_bss_anqp_free - Free an ANQP data structure
    145  * @anqp: ANQP data structure from wpa_bss_anqp_alloc() or wpa_bss_anqp_clone()
    146  */
    147 static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
    148 {
    149 #ifdef CONFIG_INTERWORKING
    150 	struct wpa_bss_anqp_elem *elem;
    151 #endif /* CONFIG_INTERWORKING */
    152 
    153 	if (anqp == NULL)
    154 		return;
    155 
    156 	anqp->users--;
    157 	if (anqp->users > 0) {
    158 		/* Another BSS entry holds a pointer to this ANQP info */
    159 		return;
    160 	}
    161 
    162 #ifdef CONFIG_INTERWORKING
    163 	wpabuf_free(anqp->capability_list);
    164 	wpabuf_free(anqp->venue_name);
    165 	wpabuf_free(anqp->network_auth_type);
    166 	wpabuf_free(anqp->roaming_consortium);
    167 	wpabuf_free(anqp->ip_addr_type_availability);
    168 	wpabuf_free(anqp->nai_realm);
    169 	wpabuf_free(anqp->anqp_3gpp);
    170 	wpabuf_free(anqp->domain_name);
    171 
    172 	while ((elem = dl_list_first(&anqp->anqp_elems,
    173 				     struct wpa_bss_anqp_elem, list))) {
    174 		dl_list_del(&elem->list);
    175 		wpabuf_free(elem->payload);
    176 		os_free(elem);
    177 	}
    178 #endif /* CONFIG_INTERWORKING */
    179 #ifdef CONFIG_HS20
    180 	wpabuf_free(anqp->hs20_capability_list);
    181 	wpabuf_free(anqp->hs20_operator_friendly_name);
    182 	wpabuf_free(anqp->hs20_wan_metrics);
    183 	wpabuf_free(anqp->hs20_connection_capability);
    184 	wpabuf_free(anqp->hs20_operating_class);
    185 	wpabuf_free(anqp->hs20_osu_providers_list);
    186 #endif /* CONFIG_HS20 */
    187 
    188 	os_free(anqp);
    189 }
    190 
    191 
    192 static void wpa_bss_update_pending_connect(struct wpa_supplicant *wpa_s,
    193 					   struct wpa_bss *old_bss,
    194 					   struct wpa_bss *new_bss)
    195 {
    196 	struct wpa_radio_work *work;
    197 	struct wpa_connect_work *cwork;
    198 
    199 	work = radio_work_pending(wpa_s, "sme-connect");
    200 	if (!work)
    201 		work = radio_work_pending(wpa_s, "connect");
    202 	if (!work)
    203 		return;
    204 
    205 	cwork = work->ctx;
    206 	if (cwork->bss != old_bss)
    207 		return;
    208 
    209 	wpa_printf(MSG_DEBUG,
    210 		   "Update BSS pointer for the pending connect radio work");
    211 	cwork->bss = new_bss;
    212 	if (!new_bss)
    213 		cwork->bss_removed = 1;
    214 }
    215 
    216 
    217 void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
    218 		    const char *reason)
    219 {
    220 	if (wpa_s->last_scan_res) {
    221 		unsigned int i;
    222 		for (i = 0; i < wpa_s->last_scan_res_used; i++) {
    223 			if (wpa_s->last_scan_res[i] == bss) {
    224 				os_memmove(&wpa_s->last_scan_res[i],
    225 					   &wpa_s->last_scan_res[i + 1],
    226 					   (wpa_s->last_scan_res_used - i - 1)
    227 					   * sizeof(struct wpa_bss *));
    228 				wpa_s->last_scan_res_used--;
    229 				break;
    230 			}
    231 		}
    232 	}
    233 	wpa_bss_update_pending_connect(wpa_s, bss, NULL);
    234 	dl_list_del(&bss->list);
    235 	dl_list_del(&bss->list_id);
    236 	wpa_s->num_bss--;
    237 	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR
    238 		" SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid),
    239 		wpa_ssid_txt(bss->ssid, bss->ssid_len), reason);
    240 	wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id);
    241 	wpa_bss_anqp_free(bss->anqp);
    242 	os_free(bss);
    243 }
    244 
    245 
    246 /**
    247  * wpa_bss_get - Fetch a BSS table entry based on BSSID and SSID
    248  * @wpa_s: Pointer to wpa_supplicant data
    249  * @bssid: BSSID
    250  * @ssid: SSID
    251  * @ssid_len: Length of @ssid
    252  * Returns: Pointer to the BSS entry or %NULL if not found
    253  */
    254 struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
    255 			     const u8 *ssid, size_t ssid_len)
    256 {
    257 	struct wpa_bss *bss;
    258 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
    259 		return NULL;
    260 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    261 		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
    262 		    bss->ssid_len == ssid_len &&
    263 		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
    264 			return bss;
    265 	}
    266 	return NULL;
    267 }
    268 
    269 
    270 static void calculate_update_time(const struct os_reltime *fetch_time,
    271 				  unsigned int age_ms,
    272 				  struct os_reltime *update_time)
    273 {
    274 	os_time_t usec;
    275 
    276 	update_time->sec = fetch_time->sec;
    277 	update_time->usec = fetch_time->usec;
    278 	update_time->sec -= age_ms / 1000;
    279 	usec = (age_ms % 1000) * 1000;
    280 	if (update_time->usec < usec) {
    281 		update_time->sec--;
    282 		update_time->usec += 1000000;
    283 	}
    284 	update_time->usec -= usec;
    285 }
    286 
    287 
    288 static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
    289 			     struct os_reltime *fetch_time)
    290 {
    291 	dst->flags = src->flags;
    292 	os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
    293 	dst->freq = src->freq;
    294 	dst->beacon_int = src->beacon_int;
    295 	dst->caps = src->caps;
    296 	dst->qual = src->qual;
    297 	dst->noise = src->noise;
    298 	dst->level = src->level;
    299 	dst->tsf = src->tsf;
    300 	dst->est_throughput = src->est_throughput;
    301 	dst->snr = src->snr;
    302 
    303 	calculate_update_time(fetch_time, src->age, &dst->last_update);
    304 }
    305 
    306 
    307 static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s,
    308 				    struct wpa_bss *bss)
    309 {
    310 #ifdef CONFIG_WPS
    311 	struct wpa_ssid *ssid;
    312 	struct wpabuf *wps_ie;
    313 	int pbc = 0, ret;
    314 
    315 	wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    316 	if (!wps_ie)
    317 		return 0;
    318 
    319 	if (wps_is_selected_pbc_registrar(wps_ie)) {
    320 		pbc = 1;
    321 	} else if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
    322 		wpabuf_free(wps_ie);
    323 		return 0;
    324 	}
    325 
    326 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    327 		if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
    328 			continue;
    329 		if (ssid->ssid_len &&
    330 		    (ssid->ssid_len != bss->ssid_len ||
    331 		     os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 0))
    332 			continue;
    333 
    334 		if (pbc)
    335 			ret = eap_is_wps_pbc_enrollee(&ssid->eap);
    336 		else
    337 			ret = eap_is_wps_pin_enrollee(&ssid->eap);
    338 		wpabuf_free(wps_ie);
    339 		return ret;
    340 	}
    341 	wpabuf_free(wps_ie);
    342 #endif /* CONFIG_WPS */
    343 
    344 	return 0;
    345 }
    346 
    347 
    348 static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
    349 {
    350 	struct wpa_ssid *ssid;
    351 
    352 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    353 		if (ssid->ssid == NULL || ssid->ssid_len == 0)
    354 			continue;
    355 		if (ssid->ssid_len == bss->ssid_len &&
    356 		    os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) == 0)
    357 			return 1;
    358 	}
    359 
    360 	return 0;
    361 }
    362 
    363 
    364 static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
    365 {
    366 	if (bss == wpa_s->current_bss)
    367 		return 1;
    368 
    369 	if (wpa_s->current_bss &&
    370 	    (bss->ssid_len != wpa_s->current_bss->ssid_len ||
    371 	     os_memcmp(bss->ssid, wpa_s->current_bss->ssid,
    372 		       bss->ssid_len) != 0))
    373 		return 0; /* SSID has changed */
    374 
    375 	return !is_zero_ether_addr(bss->bssid) &&
    376 		(os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
    377 		 os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0);
    378 }
    379 
    380 
    381 static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s)
    382 {
    383 	struct wpa_bss *bss;
    384 
    385 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    386 		if (!wpa_bss_known(wpa_s, bss) &&
    387 		    !wpa_bss_is_wps_candidate(wpa_s, bss)) {
    388 			wpa_bss_remove(wpa_s, bss, __func__);
    389 			return 0;
    390 		}
    391 	}
    392 
    393 	return -1;
    394 }
    395 
    396 
    397 static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s)
    398 {
    399 	struct wpa_bss *bss;
    400 
    401 	/*
    402 	 * Remove the oldest entry that does not match with any configured
    403 	 * network.
    404 	 */
    405 	if (wpa_bss_remove_oldest_unknown(wpa_s) == 0)
    406 		return 0;
    407 
    408 	/*
    409 	 * Remove the oldest entry that isn't currently in use.
    410 	 */
    411 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    412 		if (!wpa_bss_in_use(wpa_s, bss)) {
    413 			wpa_bss_remove(wpa_s, bss, __func__);
    414 			return 0;
    415 		}
    416 	}
    417 
    418 	return -1;
    419 }
    420 
    421 
    422 static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
    423 				    const u8 *ssid, size_t ssid_len,
    424 				    struct wpa_scan_res *res,
    425 				    struct os_reltime *fetch_time)
    426 {
    427 	struct wpa_bss *bss;
    428 
    429 	bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
    430 	if (bss == NULL)
    431 		return NULL;
    432 	bss->id = wpa_s->bss_next_id++;
    433 	bss->last_update_idx = wpa_s->bss_update_idx;
    434 	wpa_bss_copy_res(bss, res, fetch_time);
    435 	os_memcpy(bss->ssid, ssid, ssid_len);
    436 	bss->ssid_len = ssid_len;
    437 	bss->ie_len = res->ie_len;
    438 	bss->beacon_ie_len = res->beacon_ie_len;
    439 	os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
    440 	wpa_bss_set_hessid(bss);
    441 
    442 	if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count &&
    443 	    wpa_bss_remove_oldest(wpa_s) != 0) {
    444 		wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d "
    445 			   "because all BSSes are in use. We should normally "
    446 			   "not get here!", (int) wpa_s->num_bss + 1);
    447 		wpa_s->conf->bss_max_count = wpa_s->num_bss + 1;
    448 	}
    449 
    450 	dl_list_add_tail(&wpa_s->bss, &bss->list);
    451 	dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
    452 	wpa_s->num_bss++;
    453 	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
    454 		" SSID '%s' freq %d",
    455 		bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len),
    456 		bss->freq);
    457 	wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
    458 	return bss;
    459 }
    460 
    461 
    462 static int are_ies_equal(const struct wpa_bss *old,
    463 			 const struct wpa_scan_res *new_res, u32 ie)
    464 {
    465 	const u8 *old_ie, *new_ie;
    466 	struct wpabuf *old_ie_buff = NULL;
    467 	struct wpabuf *new_ie_buff = NULL;
    468 	int new_ie_len, old_ie_len, ret, is_multi;
    469 
    470 	switch (ie) {
    471 	case WPA_IE_VENDOR_TYPE:
    472 		old_ie = wpa_bss_get_vendor_ie(old, ie);
    473 		new_ie = wpa_scan_get_vendor_ie(new_res, ie);
    474 		is_multi = 0;
    475 		break;
    476 	case WPS_IE_VENDOR_TYPE:
    477 		old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie);
    478 		new_ie_buff = wpa_scan_get_vendor_ie_multi(new_res, ie);
    479 		is_multi = 1;
    480 		break;
    481 	case WLAN_EID_RSN:
    482 	case WLAN_EID_SUPP_RATES:
    483 	case WLAN_EID_EXT_SUPP_RATES:
    484 		old_ie = wpa_bss_get_ie(old, ie);
    485 		new_ie = wpa_scan_get_ie(new_res, ie);
    486 		is_multi = 0;
    487 		break;
    488 	default:
    489 		wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__);
    490 		return 0;
    491 	}
    492 
    493 	if (is_multi) {
    494 		/* in case of multiple IEs stored in buffer */
    495 		old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL;
    496 		new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL;
    497 		old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0;
    498 		new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0;
    499 	} else {
    500 		/* in case of single IE */
    501 		old_ie_len = old_ie ? old_ie[1] + 2 : 0;
    502 		new_ie_len = new_ie ? new_ie[1] + 2 : 0;
    503 	}
    504 
    505 	if (!old_ie || !new_ie)
    506 		ret = !old_ie && !new_ie;
    507 	else
    508 		ret = (old_ie_len == new_ie_len &&
    509 		       os_memcmp(old_ie, new_ie, old_ie_len) == 0);
    510 
    511 	wpabuf_free(old_ie_buff);
    512 	wpabuf_free(new_ie_buff);
    513 
    514 	return ret;
    515 }
    516 
    517 
    518 static u32 wpa_bss_compare_res(const struct wpa_bss *old,
    519 			       const struct wpa_scan_res *new_res)
    520 {
    521 	u32 changes = 0;
    522 	int caps_diff = old->caps ^ new_res->caps;
    523 
    524 	if (old->freq != new_res->freq)
    525 		changes |= WPA_BSS_FREQ_CHANGED_FLAG;
    526 
    527 	if (old->level != new_res->level)
    528 		changes |= WPA_BSS_SIGNAL_CHANGED_FLAG;
    529 
    530 	if (caps_diff & IEEE80211_CAP_PRIVACY)
    531 		changes |= WPA_BSS_PRIVACY_CHANGED_FLAG;
    532 
    533 	if (caps_diff & IEEE80211_CAP_IBSS)
    534 		changes |= WPA_BSS_MODE_CHANGED_FLAG;
    535 
    536 	if (old->ie_len == new_res->ie_len &&
    537 	    os_memcmp(old + 1, new_res + 1, old->ie_len) == 0)
    538 		return changes;
    539 	changes |= WPA_BSS_IES_CHANGED_FLAG;
    540 
    541 	if (!are_ies_equal(old, new_res, WPA_IE_VENDOR_TYPE))
    542 		changes |= WPA_BSS_WPAIE_CHANGED_FLAG;
    543 
    544 	if (!are_ies_equal(old, new_res, WLAN_EID_RSN))
    545 		changes |= WPA_BSS_RSNIE_CHANGED_FLAG;
    546 
    547 	if (!are_ies_equal(old, new_res, WPS_IE_VENDOR_TYPE))
    548 		changes |= WPA_BSS_WPS_CHANGED_FLAG;
    549 
    550 	if (!are_ies_equal(old, new_res, WLAN_EID_SUPP_RATES) ||
    551 	    !are_ies_equal(old, new_res, WLAN_EID_EXT_SUPP_RATES))
    552 		changes |= WPA_BSS_RATES_CHANGED_FLAG;
    553 
    554 	return changes;
    555 }
    556 
    557 
    558 static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
    559 			       const struct wpa_bss *bss)
    560 {
    561 	if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
    562 		wpas_notify_bss_freq_changed(wpa_s, bss->id);
    563 
    564 	if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG)
    565 		wpas_notify_bss_signal_changed(wpa_s, bss->id);
    566 
    567 	if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG)
    568 		wpas_notify_bss_privacy_changed(wpa_s, bss->id);
    569 
    570 	if (changes & WPA_BSS_MODE_CHANGED_FLAG)
    571 		wpas_notify_bss_mode_changed(wpa_s, bss->id);
    572 
    573 	if (changes & WPA_BSS_WPAIE_CHANGED_FLAG)
    574 		wpas_notify_bss_wpaie_changed(wpa_s, bss->id);
    575 
    576 	if (changes & WPA_BSS_RSNIE_CHANGED_FLAG)
    577 		wpas_notify_bss_rsnie_changed(wpa_s, bss->id);
    578 
    579 	if (changes & WPA_BSS_WPS_CHANGED_FLAG)
    580 		wpas_notify_bss_wps_changed(wpa_s, bss->id);
    581 
    582 	if (changes & WPA_BSS_IES_CHANGED_FLAG)
    583 		wpas_notify_bss_ies_changed(wpa_s, bss->id);
    584 
    585 	if (changes & WPA_BSS_RATES_CHANGED_FLAG)
    586 		wpas_notify_bss_rates_changed(wpa_s, bss->id);
    587 
    588 	wpas_notify_bss_seen(wpa_s, bss->id);
    589 }
    590 
    591 
    592 static struct wpa_bss *
    593 wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
    594 	       struct wpa_scan_res *res, struct os_reltime *fetch_time)
    595 {
    596 	u32 changes;
    597 
    598 	changes = wpa_bss_compare_res(bss, res);
    599 	if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
    600 		wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",
    601 			   MAC2STR(bss->bssid), bss->freq, res->freq);
    602 	bss->scan_miss_count = 0;
    603 	bss->last_update_idx = wpa_s->bss_update_idx;
    604 	wpa_bss_copy_res(bss, res, fetch_time);
    605 	/* Move the entry to the end of the list */
    606 	dl_list_del(&bss->list);
    607 #ifdef CONFIG_P2P
    608 	if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
    609 	    !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) {
    610 		/*
    611 		 * This can happen when non-P2P station interface runs a scan
    612 		 * without P2P IE in the Probe Request frame. P2P GO would reply
    613 		 * to that with a Probe Response that does not include P2P IE.
    614 		 * Do not update the IEs in this BSS entry to avoid such loss of
    615 		 * information that may be needed for P2P operations to
    616 		 * determine group information.
    617 		 */
    618 		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Do not update scan IEs for "
    619 			MACSTR " since that would remove P2P IE information",
    620 			MAC2STR(bss->bssid));
    621 	} else
    622 #endif /* CONFIG_P2P */
    623 	if (bss->ie_len + bss->beacon_ie_len >=
    624 	    res->ie_len + res->beacon_ie_len) {
    625 		os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
    626 		bss->ie_len = res->ie_len;
    627 		bss->beacon_ie_len = res->beacon_ie_len;
    628 	} else {
    629 		struct wpa_bss *nbss;
    630 		struct dl_list *prev = bss->list_id.prev;
    631 		dl_list_del(&bss->list_id);
    632 		nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
    633 				  res->beacon_ie_len);
    634 		if (nbss) {
    635 			unsigned int i;
    636 			for (i = 0; i < wpa_s->last_scan_res_used; i++) {
    637 				if (wpa_s->last_scan_res[i] == bss) {
    638 					wpa_s->last_scan_res[i] = nbss;
    639 					break;
    640 				}
    641 			}
    642 			if (wpa_s->current_bss == bss)
    643 				wpa_s->current_bss = nbss;
    644 			wpa_bss_update_pending_connect(wpa_s, bss, nbss);
    645 			bss = nbss;
    646 			os_memcpy(bss + 1, res + 1,
    647 				  res->ie_len + res->beacon_ie_len);
    648 			bss->ie_len = res->ie_len;
    649 			bss->beacon_ie_len = res->beacon_ie_len;
    650 		}
    651 		dl_list_add(prev, &bss->list_id);
    652 	}
    653 	if (changes & WPA_BSS_IES_CHANGED_FLAG)
    654 		wpa_bss_set_hessid(bss);
    655 	dl_list_add_tail(&wpa_s->bss, &bss->list);
    656 
    657 	notify_bss_changes(wpa_s, changes, bss);
    658 
    659 	return bss;
    660 }
    661 
    662 
    663 /**
    664  * wpa_bss_update_start - Start a BSS table update from scan results
    665  * @wpa_s: Pointer to wpa_supplicant data
    666  *
    667  * This function is called at the start of each BSS table update round for new
    668  * scan results. The actual scan result entries are indicated with calls to
    669  * wpa_bss_update_scan_res() and the update round is finished with a call to
    670  * wpa_bss_update_end().
    671  */
    672 void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
    673 {
    674 	wpa_s->bss_update_idx++;
    675 	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
    676 		wpa_s->bss_update_idx);
    677 	wpa_s->last_scan_res_used = 0;
    678 }
    679 
    680 
    681 /**
    682  * wpa_bss_update_scan_res - Update a BSS table entry based on a scan result
    683  * @wpa_s: Pointer to wpa_supplicant data
    684  * @res: Scan result
    685  * @fetch_time: Time when the result was fetched from the driver
    686  *
    687  * This function updates a BSS table entry (or adds one) based on a scan result.
    688  * This is called separately for each scan result between the calls to
    689  * wpa_bss_update_start() and wpa_bss_update_end().
    690  */
    691 void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
    692 			     struct wpa_scan_res *res,
    693 			     struct os_reltime *fetch_time)
    694 {
    695 	const u8 *ssid, *p2p, *mesh;
    696 	struct wpa_bss *bss;
    697 
    698 	if (wpa_s->conf->ignore_old_scan_res) {
    699 		struct os_reltime update;
    700 		calculate_update_time(fetch_time, res->age, &update);
    701 		if (os_reltime_before(&update, &wpa_s->scan_trigger_time)) {
    702 			struct os_reltime age;
    703 			os_reltime_sub(&wpa_s->scan_trigger_time, &update,
    704 				       &age);
    705 			wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Ignore driver BSS "
    706 				"table entry that is %u.%06u seconds older "
    707 				"than our scan trigger",
    708 				(unsigned int) age.sec,
    709 				(unsigned int) age.usec);
    710 			return;
    711 		}
    712 	}
    713 
    714 	ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
    715 	if (ssid == NULL) {
    716 		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
    717 			MACSTR, MAC2STR(res->bssid));
    718 		return;
    719 	}
    720 	if (ssid[1] > SSID_MAX_LEN) {
    721 		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for "
    722 			MACSTR, MAC2STR(res->bssid));
    723 		return;
    724 	}
    725 
    726 	p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE);
    727 #ifdef CONFIG_P2P
    728 	if (p2p == NULL &&
    729 	    wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
    730 		/*
    731 		 * If it's a P2P specific interface, then don't update
    732 		 * the scan result without a P2P IE.
    733 		 */
    734 		wpa_printf(MSG_DEBUG, "BSS: No P2P IE - skipping BSS " MACSTR
    735 			   " update for P2P interface", MAC2STR(res->bssid));
    736 		return;
    737 	}
    738 #endif /* CONFIG_P2P */
    739 	if (p2p && ssid[1] == P2P_WILDCARD_SSID_LEN &&
    740 	    os_memcmp(ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0)
    741 		return; /* Skip P2P listen discovery results here */
    742 
    743 	/* TODO: add option for ignoring BSSes we are not interested in
    744 	 * (to save memory) */
    745 
    746 	mesh = wpa_scan_get_ie(res, WLAN_EID_MESH_ID);
    747 	if (mesh && mesh[1] <= SSID_MAX_LEN)
    748 		ssid = mesh;
    749 
    750 	bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
    751 	if (bss == NULL)
    752 		bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time);
    753 	else {
    754 		bss = wpa_bss_update(wpa_s, bss, res, fetch_time);
    755 		if (wpa_s->last_scan_res) {
    756 			unsigned int i;
    757 			for (i = 0; i < wpa_s->last_scan_res_used; i++) {
    758 				if (bss == wpa_s->last_scan_res[i]) {
    759 					/* Already in the list */
    760 					return;
    761 				}
    762 			}
    763 		}
    764 	}
    765 
    766 	if (bss == NULL)
    767 		return;
    768 	if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
    769 		struct wpa_bss **n;
    770 		unsigned int siz;
    771 		if (wpa_s->last_scan_res_size == 0)
    772 			siz = 32;
    773 		else
    774 			siz = wpa_s->last_scan_res_size * 2;
    775 		n = os_realloc_array(wpa_s->last_scan_res, siz,
    776 				     sizeof(struct wpa_bss *));
    777 		if (n == NULL)
    778 			return;
    779 		wpa_s->last_scan_res = n;
    780 		wpa_s->last_scan_res_size = siz;
    781 	}
    782 
    783 	if (wpa_s->last_scan_res)
    784 		wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
    785 }
    786 
    787 
    788 static int wpa_bss_included_in_scan(const struct wpa_bss *bss,
    789 				    const struct scan_info *info)
    790 {
    791 	int found;
    792 	size_t i;
    793 
    794 	if (info == NULL)
    795 		return 1;
    796 
    797 	if (info->num_freqs) {
    798 		found = 0;
    799 		for (i = 0; i < info->num_freqs; i++) {
    800 			if (bss->freq == info->freqs[i]) {
    801 				found = 1;
    802 				break;
    803 			}
    804 		}
    805 		if (!found)
    806 			return 0;
    807 	}
    808 
    809 	if (info->num_ssids) {
    810 		found = 0;
    811 		for (i = 0; i < info->num_ssids; i++) {
    812 			const struct wpa_driver_scan_ssid *s = &info->ssids[i];
    813 			if ((s->ssid == NULL || s->ssid_len == 0) ||
    814 			    (s->ssid_len == bss->ssid_len &&
    815 			     os_memcmp(s->ssid, bss->ssid, bss->ssid_len) ==
    816 			     0)) {
    817 				found = 1;
    818 				break;
    819 			}
    820 		}
    821 		if (!found)
    822 			return 0;
    823 	}
    824 
    825 	return 1;
    826 }
    827 
    828 
    829 /**
    830  * wpa_bss_update_end - End a BSS table update from scan results
    831  * @wpa_s: Pointer to wpa_supplicant data
    832  * @info: Information about scan parameters
    833  * @new_scan: Whether this update round was based on a new scan
    834  *
    835  * This function is called at the end of each BSS table update round for new
    836  * scan results. The start of the update was indicated with a call to
    837  * wpa_bss_update_start().
    838  */
    839 void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
    840 			int new_scan)
    841 {
    842 	struct wpa_bss *bss, *n;
    843 
    844 	os_get_reltime(&wpa_s->last_scan);
    845 	if ((info && info->aborted) || !new_scan)
    846 		return; /* do not expire entries without new scan */
    847 
    848 	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
    849 		if (wpa_bss_in_use(wpa_s, bss))
    850 			continue;
    851 		if (!wpa_bss_included_in_scan(bss, info))
    852 			continue; /* expire only BSSes that were scanned */
    853 		if (bss->last_update_idx < wpa_s->bss_update_idx)
    854 			bss->scan_miss_count++;
    855 		if (bss->scan_miss_count >=
    856 		    wpa_s->conf->bss_expiration_scan_count) {
    857 			wpa_bss_remove(wpa_s, bss, "no match in scan");
    858 		}
    859 	}
    860 
    861 	wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u",
    862 		   wpa_s->last_scan_res_used, wpa_s->last_scan_res_size);
    863 }
    864 
    865 
    866 /**
    867  * wpa_bss_flush_by_age - Flush old BSS entries
    868  * @wpa_s: Pointer to wpa_supplicant data
    869  * @age: Maximum entry age in seconds
    870  *
    871  * Remove BSS entries that have not been updated during the last @age seconds.
    872  */
    873 void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age)
    874 {
    875 	struct wpa_bss *bss, *n;
    876 	struct os_reltime t;
    877 
    878 	if (dl_list_empty(&wpa_s->bss))
    879 		return;
    880 
    881 	os_get_reltime(&t);
    882 	t.sec -= age;
    883 
    884 	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
    885 		if (wpa_bss_in_use(wpa_s, bss))
    886 			continue;
    887 
    888 		if (os_reltime_before(&bss->last_update, &t)) {
    889 			wpa_bss_remove(wpa_s, bss, __func__);
    890 		} else
    891 			break;
    892 	}
    893 }
    894 
    895 
    896 /**
    897  * wpa_bss_init - Initialize BSS table
    898  * @wpa_s: Pointer to wpa_supplicant data
    899  * Returns: 0 on success, -1 on failure
    900  *
    901  * This prepares BSS table lists and timer for periodic updates. The BSS table
    902  * is deinitialized with wpa_bss_deinit() once not needed anymore.
    903  */
    904 int wpa_bss_init(struct wpa_supplicant *wpa_s)
    905 {
    906 	dl_list_init(&wpa_s->bss);
    907 	dl_list_init(&wpa_s->bss_id);
    908 	return 0;
    909 }
    910 
    911 
    912 /**
    913  * wpa_bss_flush - Flush all unused BSS entries
    914  * @wpa_s: Pointer to wpa_supplicant data
    915  */
    916 void wpa_bss_flush(struct wpa_supplicant *wpa_s)
    917 {
    918 	struct wpa_bss *bss, *n;
    919 
    920 	wpa_s->clear_driver_scan_cache = 1;
    921 
    922 	if (wpa_s->bss.next == NULL)
    923 		return; /* BSS table not yet initialized */
    924 
    925 	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
    926 		if (wpa_bss_in_use(wpa_s, bss))
    927 			continue;
    928 		wpa_bss_remove(wpa_s, bss, __func__);
    929 	}
    930 }
    931 
    932 
    933 /**
    934  * wpa_bss_deinit - Deinitialize BSS table
    935  * @wpa_s: Pointer to wpa_supplicant data
    936  */
    937 void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
    938 {
    939 	wpa_bss_flush(wpa_s);
    940 }
    941 
    942 
    943 /**
    944  * wpa_bss_get_bssid - Fetch a BSS table entry based on BSSID
    945  * @wpa_s: Pointer to wpa_supplicant data
    946  * @bssid: BSSID
    947  * Returns: Pointer to the BSS entry or %NULL if not found
    948  */
    949 struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
    950 				   const u8 *bssid)
    951 {
    952 	struct wpa_bss *bss;
    953 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
    954 		return NULL;
    955 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
    956 		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
    957 			return bss;
    958 	}
    959 	return NULL;
    960 }
    961 
    962 
    963 /**
    964  * wpa_bss_get_bssid_latest - Fetch the latest BSS table entry based on BSSID
    965  * @wpa_s: Pointer to wpa_supplicant data
    966  * @bssid: BSSID
    967  * Returns: Pointer to the BSS entry or %NULL if not found
    968  *
    969  * This function is like wpa_bss_get_bssid(), but full BSS table is iterated to
    970  * find the entry that has the most recent update. This can help in finding the
    971  * correct entry in cases where the SSID of the AP may have changed recently
    972  * (e.g., in WPS reconfiguration cases).
    973  */
    974 struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
    975 					  const u8 *bssid)
    976 {
    977 	struct wpa_bss *bss, *found = NULL;
    978 	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
    979 		return NULL;
    980 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
    981 		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
    982 			continue;
    983 		if (found == NULL ||
    984 		    os_reltime_before(&found->last_update, &bss->last_update))
    985 			found = bss;
    986 	}
    987 	return found;
    988 }
    989 
    990 
    991 #ifdef CONFIG_P2P
    992 /**
    993  * wpa_bss_get_p2p_dev_addr - Fetch a BSS table entry based on P2P Device Addr
    994  * @wpa_s: Pointer to wpa_supplicant data
    995  * @dev_addr: P2P Device Address of the GO
    996  * Returns: Pointer to the BSS entry or %NULL if not found
    997  */
    998 struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
    999 					  const u8 *dev_addr)
   1000 {
   1001 	struct wpa_bss *bss;
   1002 	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
   1003 		u8 addr[ETH_ALEN];
   1004 		if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len,
   1005 				       addr) == 0 &&
   1006 		    os_memcmp(addr, dev_addr, ETH_ALEN) == 0)
   1007 			return bss;
   1008 	}
   1009 	return NULL;
   1010 }
   1011 #endif /* CONFIG_P2P */
   1012 
   1013 
   1014 /**
   1015  * wpa_bss_get_id - Fetch a BSS table entry based on identifier
   1016  * @wpa_s: Pointer to wpa_supplicant data
   1017  * @id: Unique identifier (struct wpa_bss::id) assigned for the entry
   1018  * Returns: Pointer to the BSS entry or %NULL if not found
   1019  */
   1020 struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
   1021 {
   1022 	struct wpa_bss *bss;
   1023 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
   1024 		if (bss->id == id)
   1025 			return bss;
   1026 	}
   1027 	return NULL;
   1028 }
   1029 
   1030 
   1031 /**
   1032  * wpa_bss_get_id_range - Fetch a BSS table entry based on identifier range
   1033  * @wpa_s: Pointer to wpa_supplicant data
   1034  * @idf: Smallest allowed identifier assigned for the entry
   1035  * @idf: Largest allowed identifier assigned for the entry
   1036  * Returns: Pointer to the BSS entry or %NULL if not found
   1037  *
   1038  * This function is similar to wpa_bss_get_id() but allows a BSS entry with the
   1039  * smallest id value to be fetched within the specified range without the
   1040  * caller having to know the exact id.
   1041  */
   1042 struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
   1043 				      unsigned int idf, unsigned int idl)
   1044 {
   1045 	struct wpa_bss *bss;
   1046 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
   1047 		if (bss->id >= idf && bss->id <= idl)
   1048 			return bss;
   1049 	}
   1050 	return NULL;
   1051 }
   1052 
   1053 
   1054 /**
   1055  * wpa_bss_get_ie - Fetch a specified information element from a BSS entry
   1056  * @bss: BSS table entry
   1057  * @ie: Information element identitifier (WLAN_EID_*)
   1058  * Returns: Pointer to the information element (id field) or %NULL if not found
   1059  *
   1060  * This function returns the first matching information element in the BSS
   1061  * entry.
   1062  */
   1063 const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
   1064 {
   1065 	return get_ie((const u8 *) (bss + 1), bss->ie_len, ie);
   1066 }
   1067 
   1068 
   1069 /**
   1070  * wpa_bss_get_vendor_ie - Fetch a vendor information element from a BSS entry
   1071  * @bss: BSS table entry
   1072  * @vendor_type: Vendor type (four octets starting the IE payload)
   1073  * Returns: Pointer to the information element (id field) or %NULL if not found
   1074  *
   1075  * This function returns the first matching information element in the BSS
   1076  * entry.
   1077  */
   1078 const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
   1079 {
   1080 	const u8 *end, *pos;
   1081 
   1082 	pos = (const u8 *) (bss + 1);
   1083 	end = pos + bss->ie_len;
   1084 
   1085 	while (end - pos > 1) {
   1086 		if (2 + pos[1] > end - pos)
   1087 			break;
   1088 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
   1089 		    vendor_type == WPA_GET_BE32(&pos[2]))
   1090 			return pos;
   1091 		pos += 2 + pos[1];
   1092 	}
   1093 
   1094 	return NULL;
   1095 }
   1096 
   1097 
   1098 /**
   1099  * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry
   1100  * @bss: BSS table entry
   1101  * @vendor_type: Vendor type (four octets starting the IE payload)
   1102  * Returns: Pointer to the information element (id field) or %NULL if not found
   1103  *
   1104  * This function returns the first matching information element in the BSS
   1105  * entry.
   1106  *
   1107  * This function is like wpa_bss_get_vendor_ie(), but uses IE buffer only
   1108  * from Beacon frames instead of either Beacon or Probe Response frames.
   1109  */
   1110 const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
   1111 					u32 vendor_type)
   1112 {
   1113 	const u8 *end, *pos;
   1114 
   1115 	if (bss->beacon_ie_len == 0)
   1116 		return NULL;
   1117 
   1118 	pos = (const u8 *) (bss + 1);
   1119 	pos += bss->ie_len;
   1120 	end = pos + bss->beacon_ie_len;
   1121 
   1122 	while (end - pos > 1) {
   1123 		if (2 + pos[1] > end - pos)
   1124 			break;
   1125 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
   1126 		    vendor_type == WPA_GET_BE32(&pos[2]))
   1127 			return pos;
   1128 		pos += 2 + pos[1];
   1129 	}
   1130 
   1131 	return NULL;
   1132 }
   1133 
   1134 
   1135 /**
   1136  * wpa_bss_get_vendor_ie_multi - Fetch vendor IE data from a BSS entry
   1137  * @bss: BSS table entry
   1138  * @vendor_type: Vendor type (four octets starting the IE payload)
   1139  * Returns: Pointer to the information element payload or %NULL if not found
   1140  *
   1141  * This function returns concatenated payload of possibly fragmented vendor
   1142  * specific information elements in the BSS entry. The caller is responsible for
   1143  * freeing the returned buffer.
   1144  */
   1145 struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
   1146 					    u32 vendor_type)
   1147 {
   1148 	struct wpabuf *buf;
   1149 	const u8 *end, *pos;
   1150 
   1151 	buf = wpabuf_alloc(bss->ie_len);
   1152 	if (buf == NULL)
   1153 		return NULL;
   1154 
   1155 	pos = (const u8 *) (bss + 1);
   1156 	end = pos + bss->ie_len;
   1157 
   1158 	while (end - pos > 1) {
   1159 		if (2 + pos[1] > end - pos)
   1160 			break;
   1161 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
   1162 		    vendor_type == WPA_GET_BE32(&pos[2]))
   1163 			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
   1164 		pos += 2 + pos[1];
   1165 	}
   1166 
   1167 	if (wpabuf_len(buf) == 0) {
   1168 		wpabuf_free(buf);
   1169 		buf = NULL;
   1170 	}
   1171 
   1172 	return buf;
   1173 }
   1174 
   1175 
   1176 /**
   1177  * wpa_bss_get_vendor_ie_multi_beacon - Fetch vendor IE data from a BSS entry
   1178  * @bss: BSS table entry
   1179  * @vendor_type: Vendor type (four octets starting the IE payload)
   1180  * Returns: Pointer to the information element payload or %NULL if not found
   1181  *
   1182  * This function returns concatenated payload of possibly fragmented vendor
   1183  * specific information elements in the BSS entry. The caller is responsible for
   1184  * freeing the returned buffer.
   1185  *
   1186  * This function is like wpa_bss_get_vendor_ie_multi(), but uses IE buffer only
   1187  * from Beacon frames instead of either Beacon or Probe Response frames.
   1188  */
   1189 struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
   1190 						   u32 vendor_type)
   1191 {
   1192 	struct wpabuf *buf;
   1193 	const u8 *end, *pos;
   1194 
   1195 	buf = wpabuf_alloc(bss->beacon_ie_len);
   1196 	if (buf == NULL)
   1197 		return NULL;
   1198 
   1199 	pos = (const u8 *) (bss + 1);
   1200 	pos += bss->ie_len;
   1201 	end = pos + bss->beacon_ie_len;
   1202 
   1203 	while (end - pos > 1) {
   1204 		if (2 + pos[1] > end - pos)
   1205 			break;
   1206 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
   1207 		    vendor_type == WPA_GET_BE32(&pos[2]))
   1208 			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
   1209 		pos += 2 + pos[1];
   1210 	}
   1211 
   1212 	if (wpabuf_len(buf) == 0) {
   1213 		wpabuf_free(buf);
   1214 		buf = NULL;
   1215 	}
   1216 
   1217 	return buf;
   1218 }
   1219 
   1220 
   1221 /**
   1222  * wpa_bss_get_max_rate - Get maximum legacy TX rate supported in a BSS
   1223  * @bss: BSS table entry
   1224  * Returns: Maximum legacy rate in units of 500 kbps
   1225  */
   1226 int wpa_bss_get_max_rate(const struct wpa_bss *bss)
   1227 {
   1228 	int rate = 0;
   1229 	const u8 *ie;
   1230 	int i;
   1231 
   1232 	ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
   1233 	for (i = 0; ie && i < ie[1]; i++) {
   1234 		if ((ie[i + 2] & 0x7f) > rate)
   1235 			rate = ie[i + 2] & 0x7f;
   1236 	}
   1237 
   1238 	ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
   1239 	for (i = 0; ie && i < ie[1]; i++) {
   1240 		if ((ie[i + 2] & 0x7f) > rate)
   1241 			rate = ie[i + 2] & 0x7f;
   1242 	}
   1243 
   1244 	return rate;
   1245 }
   1246 
   1247 
   1248 /**
   1249  * wpa_bss_get_bit_rates - Get legacy TX rates supported in a BSS
   1250  * @bss: BSS table entry
   1251  * @rates: Buffer for returning a pointer to the rates list (units of 500 kbps)
   1252  * Returns: number of legacy TX rates or -1 on failure
   1253  *
   1254  * The caller is responsible for freeing the returned buffer with os_free() in
   1255  * case of success.
   1256  */
   1257 int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
   1258 {
   1259 	const u8 *ie, *ie2;
   1260 	int i, j;
   1261 	unsigned int len;
   1262 	u8 *r;
   1263 
   1264 	ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
   1265 	ie2 = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
   1266 
   1267 	len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0);
   1268 
   1269 	r = os_malloc(len);
   1270 	if (!r)
   1271 		return -1;
   1272 
   1273 	for (i = 0; ie && i < ie[1]; i++)
   1274 		r[i] = ie[i + 2] & 0x7f;
   1275 
   1276 	for (j = 0; ie2 && j < ie2[1]; j++)
   1277 		r[i + j] = ie2[j + 2] & 0x7f;
   1278 
   1279 	*rates = r;
   1280 	return len;
   1281 }
   1282