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