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