3 * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/ieee802_11_defs.h"
14 #include "drivers/driver.h"
15 #include "wpa_supplicant_i.h"
23 * WPA_BSS_EXPIRATION_PERIOD - Period of expiration run in seconds
25 #define WPA_BSS_EXPIRATION_PERIOD 10
27 #define WPA_BSS_FREQ_CHANGED_FLAG BIT(0)
28 #define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1)
29 #define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2)
30 #define WPA_BSS_MODE_CHANGED_FLAG BIT(3)
31 #define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4)
32 #define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5)
33 #define WPA_BSS_WPS_CHANGED_FLAG BIT(6)
34 #define WPA_BSS_RATES_CHANGED_FLAG BIT(7)
35 #define WPA_BSS_IES_CHANGED_FLAG BIT(8)
38 static void wpa_bss_set_hessid(struct wpa_bss
*bss
)
40 #ifdef CONFIG_INTERWORKING
41 const u8
*ie
= wpa_bss_get_ie(bss
, WLAN_EID_INTERWORKING
);
42 if (ie
== NULL
|| (ie
[1] != 7 && ie
[1] != 9)) {
43 os_memset(bss
->hessid
, 0, ETH_ALEN
);
47 os_memcpy(bss
->hessid
, ie
+ 3, ETH_ALEN
);
49 os_memcpy(bss
->hessid
, ie
+ 5, ETH_ALEN
);
50 #endif /* CONFIG_INTERWORKING */
54 struct wpa_bss_anqp
* wpa_bss_anqp_alloc(void)
56 struct wpa_bss_anqp
*anqp
;
57 anqp
= os_zalloc(sizeof(*anqp
));
65 static void wpa_bss_anqp_free(struct wpa_bss_anqp
*anqp
)
71 if (anqp
->users
> 0) {
72 /* Another BSS entry holds a pointer to this ANQP info */
76 #ifdef CONFIG_INTERWORKING
77 wpabuf_free(anqp
->venue_name
);
78 wpabuf_free(anqp
->network_auth_type
);
79 wpabuf_free(anqp
->roaming_consortium
);
80 wpabuf_free(anqp
->ip_addr_type_availability
);
81 wpabuf_free(anqp
->nai_realm
);
82 wpabuf_free(anqp
->anqp_3gpp
);
83 wpabuf_free(anqp
->domain_name
);
84 #endif /* CONFIG_INTERWORKING */
86 wpabuf_free(anqp
->hs20_operator_friendly_name
);
87 wpabuf_free(anqp
->hs20_wan_metrics
);
88 wpabuf_free(anqp
->hs20_connection_capability
);
89 wpabuf_free(anqp
->hs20_operating_class
);
90 #endif /* CONFIG_HS20 */
96 static void wpa_bss_remove(struct wpa_supplicant
*wpa_s
, struct wpa_bss
*bss
,
99 if (wpa_s
->last_scan_res
) {
101 for (i
= 0; i
< wpa_s
->last_scan_res_used
; i
++) {
102 if (wpa_s
->last_scan_res
[i
] == bss
) {
103 os_memmove(&wpa_s
->last_scan_res
[i
],
104 &wpa_s
->last_scan_res
[i
+ 1],
105 (wpa_s
->last_scan_res_used
- i
- 1)
106 * sizeof(struct wpa_bss
*));
107 wpa_s
->last_scan_res_used
--;
112 dl_list_del(&bss
->list
);
113 dl_list_del(&bss
->list_id
);
115 wpa_dbg(wpa_s
, MSG_DEBUG
, "BSS: Remove id %u BSSID " MACSTR
116 " SSID '%s' due to %s", bss
->id
, MAC2STR(bss
->bssid
),
117 wpa_ssid_txt(bss
->ssid
, bss
->ssid_len
), reason
);
118 wpas_notify_bss_removed(wpa_s
, bss
->bssid
, bss
->id
);
119 wpa_bss_anqp_free(bss
->anqp
);
124 struct wpa_bss
* wpa_bss_get(struct wpa_supplicant
*wpa_s
, const u8
*bssid
,
125 const u8
*ssid
, size_t ssid_len
)
128 if (!wpa_supplicant_filter_bssid_match(wpa_s
, bssid
))
130 dl_list_for_each(bss
, &wpa_s
->bss
, struct wpa_bss
, list
) {
131 if (os_memcmp(bss
->bssid
, bssid
, ETH_ALEN
) == 0 &&
132 bss
->ssid_len
== ssid_len
&&
133 os_memcmp(bss
->ssid
, ssid
, ssid_len
) == 0)
140 static void wpa_bss_copy_res(struct wpa_bss
*dst
, struct wpa_scan_res
*src
)
144 dst
->flags
= src
->flags
;
145 os_memcpy(dst
->bssid
, src
->bssid
, ETH_ALEN
);
146 dst
->freq
= src
->freq
;
147 dst
->beacon_int
= src
->beacon_int
;
148 dst
->caps
= src
->caps
;
149 dst
->qual
= src
->qual
;
150 dst
->noise
= src
->noise
;
151 dst
->level
= src
->level
;
154 os_get_time(&dst
->last_update
);
155 dst
->last_update
.sec
-= src
->age
/ 1000;
156 usec
= (src
->age
% 1000) * 1000;
157 if (dst
->last_update
.usec
< usec
) {
158 dst
->last_update
.sec
--;
159 dst
->last_update
.usec
+= 1000000;
161 dst
->last_update
.usec
-= usec
;
165 static int wpa_bss_known(struct wpa_supplicant
*wpa_s
, struct wpa_bss
*bss
)
167 struct wpa_ssid
*ssid
;
169 for (ssid
= wpa_s
->conf
->ssid
; ssid
; ssid
= ssid
->next
) {
170 if (ssid
->ssid
== NULL
|| ssid
->ssid_len
== 0)
172 if (ssid
->ssid_len
== bss
->ssid_len
&&
173 os_memcmp(ssid
->ssid
, bss
->ssid
, ssid
->ssid_len
) == 0)
181 static int wpa_bss_in_use(struct wpa_supplicant
*wpa_s
, struct wpa_bss
*bss
)
183 return bss
== wpa_s
->current_bss
||
184 os_memcmp(bss
->bssid
, wpa_s
->bssid
, ETH_ALEN
) == 0 ||
185 os_memcmp(bss
->bssid
, wpa_s
->pending_bssid
, ETH_ALEN
) == 0;
189 static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant
*wpa_s
)
193 dl_list_for_each(bss
, &wpa_s
->bss
, struct wpa_bss
, list
) {
194 if (!wpa_bss_known(wpa_s
, bss
)) {
195 wpa_bss_remove(wpa_s
, bss
, __func__
);
204 static int wpa_bss_remove_oldest(struct wpa_supplicant
*wpa_s
)
209 * Remove the oldest entry that does not match with any configured
212 if (wpa_bss_remove_oldest_unknown(wpa_s
) == 0)
216 * Remove the oldest entry that isn't currently in use.
218 dl_list_for_each(bss
, &wpa_s
->bss
, struct wpa_bss
, list
) {
219 if (!wpa_bss_in_use(wpa_s
, bss
)) {
220 wpa_bss_remove(wpa_s
, bss
, __func__
);
229 static struct wpa_bss
* wpa_bss_add(struct wpa_supplicant
*wpa_s
,
230 const u8
*ssid
, size_t ssid_len
,
231 struct wpa_scan_res
*res
)
235 bss
= os_zalloc(sizeof(*bss
) + res
->ie_len
+ res
->beacon_ie_len
);
238 bss
->id
= wpa_s
->bss_next_id
++;
239 bss
->last_update_idx
= wpa_s
->bss_update_idx
;
240 wpa_bss_copy_res(bss
, res
);
241 os_memcpy(bss
->ssid
, ssid
, ssid_len
);
242 bss
->ssid_len
= ssid_len
;
243 bss
->ie_len
= res
->ie_len
;
244 bss
->beacon_ie_len
= res
->beacon_ie_len
;
245 os_memcpy(bss
+ 1, res
+ 1, res
->ie_len
+ res
->beacon_ie_len
);
246 wpa_bss_set_hessid(bss
);
248 dl_list_add_tail(&wpa_s
->bss
, &bss
->list
);
249 dl_list_add_tail(&wpa_s
->bss_id
, &bss
->list_id
);
251 wpa_dbg(wpa_s
, MSG_DEBUG
, "BSS: Add new id %u BSSID " MACSTR
253 bss
->id
, MAC2STR(bss
->bssid
), wpa_ssid_txt(ssid
, ssid_len
));
254 wpas_notify_bss_added(wpa_s
, bss
->bssid
, bss
->id
);
255 if (wpa_s
->num_bss
> wpa_s
->conf
->bss_max_count
&&
256 wpa_bss_remove_oldest(wpa_s
) != 0) {
257 wpa_printf(MSG_ERROR
, "Increasing the MAX BSS count to %d "
258 "because all BSSes are in use. We should normally "
259 "not get here!", (int) wpa_s
->num_bss
);
260 wpa_s
->conf
->bss_max_count
= wpa_s
->num_bss
;
266 static int are_ies_equal(const struct wpa_bss
*old
,
267 const struct wpa_scan_res
*new, u32 ie
)
269 const u8
*old_ie
, *new_ie
;
270 struct wpabuf
*old_ie_buff
= NULL
;
271 struct wpabuf
*new_ie_buff
= NULL
;
272 int new_ie_len
, old_ie_len
, ret
, is_multi
;
275 case WPA_IE_VENDOR_TYPE
:
276 old_ie
= wpa_bss_get_vendor_ie(old
, ie
);
277 new_ie
= wpa_scan_get_vendor_ie(new, ie
);
280 case WPS_IE_VENDOR_TYPE
:
281 old_ie_buff
= wpa_bss_get_vendor_ie_multi(old
, ie
);
282 new_ie_buff
= wpa_scan_get_vendor_ie_multi(new, ie
);
286 case WLAN_EID_SUPP_RATES
:
287 case WLAN_EID_EXT_SUPP_RATES
:
288 old_ie
= wpa_bss_get_ie(old
, ie
);
289 new_ie
= wpa_scan_get_ie(new, ie
);
293 wpa_printf(MSG_DEBUG
, "bss: %s: cannot compare IEs", __func__
);
298 /* in case of multiple IEs stored in buffer */
299 old_ie
= old_ie_buff
? wpabuf_head_u8(old_ie_buff
) : NULL
;
300 new_ie
= new_ie_buff
? wpabuf_head_u8(new_ie_buff
) : NULL
;
301 old_ie_len
= old_ie_buff
? wpabuf_len(old_ie_buff
) : 0;
302 new_ie_len
= new_ie_buff
? wpabuf_len(new_ie_buff
) : 0;
304 /* in case of single IE */
305 old_ie_len
= old_ie
? old_ie
[1] + 2 : 0;
306 new_ie_len
= new_ie
? new_ie
[1] + 2 : 0;
309 if (!old_ie
|| !new_ie
)
310 ret
= !old_ie
&& !new_ie
;
312 ret
= (old_ie_len
== new_ie_len
&&
313 os_memcmp(old_ie
, new_ie
, old_ie_len
) == 0);
315 wpabuf_free(old_ie_buff
);
316 wpabuf_free(new_ie_buff
);
322 static u32
wpa_bss_compare_res(const struct wpa_bss
*old
,
323 const struct wpa_scan_res
*new)
326 int caps_diff
= old
->caps
^ new->caps
;
328 if (old
->freq
!= new->freq
)
329 changes
|= WPA_BSS_FREQ_CHANGED_FLAG
;
331 if (old
->level
!= new->level
)
332 changes
|= WPA_BSS_SIGNAL_CHANGED_FLAG
;
334 if (caps_diff
& IEEE80211_CAP_PRIVACY
)
335 changes
|= WPA_BSS_PRIVACY_CHANGED_FLAG
;
337 if (caps_diff
& IEEE80211_CAP_IBSS
)
338 changes
|= WPA_BSS_MODE_CHANGED_FLAG
;
340 if (old
->ie_len
== new->ie_len
&&
341 os_memcmp(old
+ 1, new + 1, old
->ie_len
) == 0)
343 changes
|= WPA_BSS_IES_CHANGED_FLAG
;
345 if (!are_ies_equal(old
, new, WPA_IE_VENDOR_TYPE
))
346 changes
|= WPA_BSS_WPAIE_CHANGED_FLAG
;
348 if (!are_ies_equal(old
, new, WLAN_EID_RSN
))
349 changes
|= WPA_BSS_RSNIE_CHANGED_FLAG
;
351 if (!are_ies_equal(old
, new, WPS_IE_VENDOR_TYPE
))
352 changes
|= WPA_BSS_WPS_CHANGED_FLAG
;
354 if (!are_ies_equal(old
, new, WLAN_EID_SUPP_RATES
) ||
355 !are_ies_equal(old
, new, WLAN_EID_EXT_SUPP_RATES
))
356 changes
|= WPA_BSS_RATES_CHANGED_FLAG
;
362 static void notify_bss_changes(struct wpa_supplicant
*wpa_s
, u32 changes
,
363 const struct wpa_bss
*bss
)
365 if (changes
& WPA_BSS_FREQ_CHANGED_FLAG
)
366 wpas_notify_bss_freq_changed(wpa_s
, bss
->id
);
368 if (changes
& WPA_BSS_SIGNAL_CHANGED_FLAG
)
369 wpas_notify_bss_signal_changed(wpa_s
, bss
->id
);
371 if (changes
& WPA_BSS_PRIVACY_CHANGED_FLAG
)
372 wpas_notify_bss_privacy_changed(wpa_s
, bss
->id
);
374 if (changes
& WPA_BSS_MODE_CHANGED_FLAG
)
375 wpas_notify_bss_mode_changed(wpa_s
, bss
->id
);
377 if (changes
& WPA_BSS_WPAIE_CHANGED_FLAG
)
378 wpas_notify_bss_wpaie_changed(wpa_s
, bss
->id
);
380 if (changes
& WPA_BSS_RSNIE_CHANGED_FLAG
)
381 wpas_notify_bss_rsnie_changed(wpa_s
, bss
->id
);
383 if (changes
& WPA_BSS_WPS_CHANGED_FLAG
)
384 wpas_notify_bss_wps_changed(wpa_s
, bss
->id
);
386 if (changes
& WPA_BSS_IES_CHANGED_FLAG
)
387 wpas_notify_bss_ies_changed(wpa_s
, bss
->id
);
389 if (changes
& WPA_BSS_RATES_CHANGED_FLAG
)
390 wpas_notify_bss_rates_changed(wpa_s
, bss
->id
);
394 static struct wpa_bss
*
395 wpa_bss_update(struct wpa_supplicant
*wpa_s
, struct wpa_bss
*bss
,
396 struct wpa_scan_res
*res
)
400 changes
= wpa_bss_compare_res(bss
, res
);
401 bss
->scan_miss_count
= 0;
402 bss
->last_update_idx
= wpa_s
->bss_update_idx
;
403 wpa_bss_copy_res(bss
, res
);
404 /* Move the entry to the end of the list */
405 dl_list_del(&bss
->list
);
406 if (bss
->ie_len
+ bss
->beacon_ie_len
>=
407 res
->ie_len
+ res
->beacon_ie_len
) {
408 os_memcpy(bss
+ 1, res
+ 1, res
->ie_len
+ res
->beacon_ie_len
);
409 bss
->ie_len
= res
->ie_len
;
410 bss
->beacon_ie_len
= res
->beacon_ie_len
;
412 struct wpa_bss
*nbss
;
413 struct dl_list
*prev
= bss
->list_id
.prev
;
414 dl_list_del(&bss
->list_id
);
415 nbss
= os_realloc(bss
, sizeof(*bss
) + res
->ie_len
+
419 for (i
= 0; i
< wpa_s
->last_scan_res_used
; i
++) {
420 if (wpa_s
->last_scan_res
[i
] == bss
) {
421 wpa_s
->last_scan_res
[i
] = nbss
;
425 if (wpa_s
->current_bss
== bss
)
426 wpa_s
->current_bss
= nbss
;
428 os_memcpy(bss
+ 1, res
+ 1,
429 res
->ie_len
+ res
->beacon_ie_len
);
430 bss
->ie_len
= res
->ie_len
;
431 bss
->beacon_ie_len
= res
->beacon_ie_len
;
433 dl_list_add(prev
, &bss
->list_id
);
435 if (changes
& WPA_BSS_IES_CHANGED_FLAG
)
436 wpa_bss_set_hessid(bss
);
437 dl_list_add_tail(&wpa_s
->bss
, &bss
->list
);
439 notify_bss_changes(wpa_s
, changes
, bss
);
445 void wpa_bss_update_start(struct wpa_supplicant
*wpa_s
)
447 wpa_s
->bss_update_idx
++;
448 wpa_dbg(wpa_s
, MSG_DEBUG
, "BSS: Start scan result update %u",
449 wpa_s
->bss_update_idx
);
450 wpa_s
->last_scan_res_used
= 0;
454 void wpa_bss_update_scan_res(struct wpa_supplicant
*wpa_s
,
455 struct wpa_scan_res
*res
)
457 const u8
*ssid
, *p2p
;
460 ssid
= wpa_scan_get_ie(res
, WLAN_EID_SSID
);
462 wpa_dbg(wpa_s
, MSG_DEBUG
, "BSS: No SSID IE included for "
463 MACSTR
, MAC2STR(res
->bssid
));
467 wpa_dbg(wpa_s
, MSG_DEBUG
, "BSS: Too long SSID IE included for "
468 MACSTR
, MAC2STR(res
->bssid
));
472 p2p
= wpa_scan_get_vendor_ie(res
, P2P_IE_VENDOR_TYPE
);
475 wpa_s
->p2p_group_interface
!= NOT_P2P_GROUP_INTERFACE
) {
477 * If it's a P2P specific interface, then don't update
478 * the scan result without a P2P IE.
480 wpa_printf(MSG_DEBUG
, "BSS: No P2P IE - skipping BSS " MACSTR
481 " update for P2P interface", MAC2STR(res
->bssid
));
484 #endif /* CONFIG_P2P */
485 if (p2p
&& ssid
[1] == P2P_WILDCARD_SSID_LEN
&&
486 os_memcmp(ssid
+ 2, P2P_WILDCARD_SSID
, P2P_WILDCARD_SSID_LEN
) == 0)
487 return; /* Skip P2P listen discovery results here */
489 /* TODO: add option for ignoring BSSes we are not interested in
490 * (to save memory) */
491 bss
= wpa_bss_get(wpa_s
, res
->bssid
, ssid
+ 2, ssid
[1]);
493 bss
= wpa_bss_add(wpa_s
, ssid
+ 2, ssid
[1], res
);
495 bss
= wpa_bss_update(wpa_s
, bss
, res
);
499 if (wpa_s
->last_scan_res_used
>= wpa_s
->last_scan_res_size
) {
502 if (wpa_s
->last_scan_res_size
== 0)
505 siz
= wpa_s
->last_scan_res_size
* 2;
506 n
= os_realloc_array(wpa_s
->last_scan_res
, siz
,
507 sizeof(struct wpa_bss
*));
510 wpa_s
->last_scan_res
= n
;
511 wpa_s
->last_scan_res_size
= siz
;
514 wpa_s
->last_scan_res
[wpa_s
->last_scan_res_used
++] = bss
;
518 static int wpa_bss_included_in_scan(const struct wpa_bss
*bss
,
519 const struct scan_info
*info
)
527 if (info
->num_freqs
) {
529 for (i
= 0; i
< info
->num_freqs
; i
++) {
530 if (bss
->freq
== info
->freqs
[i
]) {
539 if (info
->num_ssids
) {
541 for (i
= 0; i
< info
->num_ssids
; i
++) {
542 const struct wpa_driver_scan_ssid
*s
= &info
->ssids
[i
];
543 if ((s
->ssid
== NULL
|| s
->ssid_len
== 0) ||
544 (s
->ssid_len
== bss
->ssid_len
&&
545 os_memcmp(s
->ssid
, bss
->ssid
, bss
->ssid_len
) ==
559 void wpa_bss_update_end(struct wpa_supplicant
*wpa_s
, struct scan_info
*info
,
562 struct wpa_bss
*bss
, *n
;
564 wpa_s
->last_scan_full
= 0;
565 os_get_time(&wpa_s
->last_scan
);
567 return; /* do not expire entries without new scan */
569 if (info
&& !info
->aborted
&& !info
->freqs
) {
571 if (info
->num_ssids
== 0) {
572 wpa_s
->last_scan_full
= 1;
574 for (i
= 0; i
< info
->num_ssids
; i
++) {
575 if (info
->ssids
[i
].ssid
== NULL
||
576 info
->ssids
[i
].ssid_len
== 0) {
577 wpa_s
->last_scan_full
= 1;
584 dl_list_for_each_safe(bss
, n
, &wpa_s
->bss
, struct wpa_bss
, list
) {
585 if (wpa_bss_in_use(wpa_s
, bss
))
587 if (!wpa_bss_included_in_scan(bss
, info
))
588 continue; /* expire only BSSes that were scanned */
589 if (bss
->last_update_idx
< wpa_s
->bss_update_idx
)
590 bss
->scan_miss_count
++;
591 if (bss
->scan_miss_count
>=
592 wpa_s
->conf
->bss_expiration_scan_count
) {
593 wpa_bss_remove(wpa_s
, bss
, "no match in scan");
597 wpa_printf(MSG_DEBUG
, "BSS: last_scan_res_used=%u/%u "
599 wpa_s
->last_scan_res_used
, wpa_s
->last_scan_res_size
,
600 wpa_s
->last_scan_full
);
604 void wpa_bss_flush_by_age(struct wpa_supplicant
*wpa_s
, int age
)
606 struct wpa_bss
*bss
, *n
;
609 if (dl_list_empty(&wpa_s
->bss
))
615 dl_list_for_each_safe(bss
, n
, &wpa_s
->bss
, struct wpa_bss
, list
) {
616 if (wpa_bss_in_use(wpa_s
, bss
))
619 if (os_time_before(&bss
->last_update
, &t
)) {
620 wpa_bss_remove(wpa_s
, bss
, __func__
);
627 static void wpa_bss_timeout(void *eloop_ctx
, void *timeout_ctx
)
629 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
631 wpa_bss_flush_by_age(wpa_s
, wpa_s
->conf
->bss_expiration_age
);
632 eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD
, 0,
633 wpa_bss_timeout
, wpa_s
, NULL
);
637 int wpa_bss_init(struct wpa_supplicant
*wpa_s
)
639 dl_list_init(&wpa_s
->bss
);
640 dl_list_init(&wpa_s
->bss_id
);
641 eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD
, 0,
642 wpa_bss_timeout
, wpa_s
, NULL
);
647 void wpa_bss_flush(struct wpa_supplicant
*wpa_s
)
649 struct wpa_bss
*bss
, *n
;
651 if (wpa_s
->bss
.next
== NULL
)
652 return; /* BSS table not yet initialized */
654 dl_list_for_each_safe(bss
, n
, &wpa_s
->bss
, struct wpa_bss
, list
) {
655 if (wpa_bss_in_use(wpa_s
, bss
))
657 wpa_bss_remove(wpa_s
, bss
, __func__
);
662 void wpa_bss_deinit(struct wpa_supplicant
*wpa_s
)
664 eloop_cancel_timeout(wpa_bss_timeout
, wpa_s
, NULL
);
665 wpa_bss_flush(wpa_s
);
669 struct wpa_bss
* wpa_bss_get_bssid(struct wpa_supplicant
*wpa_s
,
673 if (!wpa_supplicant_filter_bssid_match(wpa_s
, bssid
))
675 dl_list_for_each_reverse(bss
, &wpa_s
->bss
, struct wpa_bss
, list
) {
676 if (os_memcmp(bss
->bssid
, bssid
, ETH_ALEN
) == 0)
684 struct wpa_bss
* wpa_bss_get_p2p_dev_addr(struct wpa_supplicant
*wpa_s
,
688 dl_list_for_each_reverse(bss
, &wpa_s
->bss
, struct wpa_bss
, list
) {
690 if (p2p_parse_dev_addr((const u8
*) (bss
+ 1), bss
->ie_len
,
692 os_memcmp(addr
, dev_addr
, ETH_ALEN
) == 0)
697 #endif /* CONFIG_P2P */
700 struct wpa_bss
* wpa_bss_get_id(struct wpa_supplicant
*wpa_s
, unsigned int id
)
703 dl_list_for_each(bss
, &wpa_s
->bss
, struct wpa_bss
, list
) {
711 const u8
* wpa_bss_get_ie(const struct wpa_bss
*bss
, u8 ie
)
715 pos
= (const u8
*) (bss
+ 1);
716 end
= pos
+ bss
->ie_len
;
718 while (pos
+ 1 < end
) {
719 if (pos
+ 2 + pos
[1] > end
)
730 const u8
* wpa_bss_get_vendor_ie(const struct wpa_bss
*bss
, u32 vendor_type
)
734 pos
= (const u8
*) (bss
+ 1);
735 end
= pos
+ bss
->ie_len
;
737 while (pos
+ 1 < end
) {
738 if (pos
+ 2 + pos
[1] > end
)
740 if (pos
[0] == WLAN_EID_VENDOR_SPECIFIC
&& pos
[1] >= 4 &&
741 vendor_type
== WPA_GET_BE32(&pos
[2]))
750 struct wpabuf
* wpa_bss_get_vendor_ie_multi(const struct wpa_bss
*bss
,
756 buf
= wpabuf_alloc(bss
->ie_len
);
760 pos
= (const u8
*) (bss
+ 1);
761 end
= pos
+ bss
->ie_len
;
763 while (pos
+ 1 < end
) {
764 if (pos
+ 2 + pos
[1] > end
)
766 if (pos
[0] == WLAN_EID_VENDOR_SPECIFIC
&& pos
[1] >= 4 &&
767 vendor_type
== WPA_GET_BE32(&pos
[2]))
768 wpabuf_put_data(buf
, pos
+ 2 + 4, pos
[1] - 4);
772 if (wpabuf_len(buf
) == 0) {
781 struct wpabuf
* wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss
*bss
,
787 buf
= wpabuf_alloc(bss
->beacon_ie_len
);
791 pos
= (const u8
*) (bss
+ 1);
793 end
= pos
+ bss
->beacon_ie_len
;
795 while (pos
+ 1 < end
) {
796 if (pos
+ 2 + pos
[1] > end
)
798 if (pos
[0] == WLAN_EID_VENDOR_SPECIFIC
&& pos
[1] >= 4 &&
799 vendor_type
== WPA_GET_BE32(&pos
[2]))
800 wpabuf_put_data(buf
, pos
+ 2 + 4, pos
[1] - 4);
804 if (wpabuf_len(buf
) == 0) {
813 int wpa_bss_get_max_rate(const struct wpa_bss
*bss
)
819 ie
= wpa_bss_get_ie(bss
, WLAN_EID_SUPP_RATES
);
820 for (i
= 0; ie
&& i
< ie
[1]; i
++) {
821 if ((ie
[i
+ 2] & 0x7f) > rate
)
822 rate
= ie
[i
+ 2] & 0x7f;
825 ie
= wpa_bss_get_ie(bss
, WLAN_EID_EXT_SUPP_RATES
);
826 for (i
= 0; ie
&& i
< ie
[1]; i
++) {
827 if ((ie
[i
+ 2] & 0x7f) > rate
)
828 rate
= ie
[i
+ 2] & 0x7f;
835 int wpa_bss_get_bit_rates(const struct wpa_bss
*bss
, u8
**rates
)
842 ie
= wpa_bss_get_ie(bss
, WLAN_EID_SUPP_RATES
);
843 ie2
= wpa_bss_get_ie(bss
, WLAN_EID_EXT_SUPP_RATES
);
845 len
= (ie
? ie
[1] : 0) + (ie2
? ie2
[1] : 0);
851 for (i
= 0; ie
&& i
< ie
[1]; i
++)
852 r
[i
] = ie
[i
+ 2] & 0x7f;
854 for (j
= 0; ie2
&& j
< ie2
[1]; j
++)
855 r
[i
+ j
] = ie2
[j
+ 2] & 0x7f;