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