TDLS: Declare tdls_testing as extern in a header file
[mech_eap.git] / wpa_supplicant / bss.c
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 static 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 }