1 /* 2 * BSS table 3 * Copyright (c) 2009-2015, Jouni Malinen <j (at) 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 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 */ 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 */ 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 * 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 1321 1322 #ifdef CONFIG_FILS 1323 const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss) 1324 { 1325 const u8 *ie; 1326 1327 if (bss) { 1328 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION); 1329 if (ie && ie[1] >= 4 && WPA_GET_LE16(ie + 2) & BIT(7)) 1330 return ie + 4; 1331 } 1332 1333 return NULL; 1334 } 1335 #endif /* CONFIG_FILS */ 1336