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