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