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