xref: /freebsd/contrib/wpa/wpa_supplicant/bss.c (revision 78b9f0095b4af3aca6c931b2c7b009ddb8a05125)
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 
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