1 /* 2 * WPA Supplicant - Scanning 3 * Copyright (c) 2003-2010, Jouni Malinen <j (at) w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "utils/includes.h" 16 17 #include "utils/common.h" 18 #include "utils/eloop.h" 19 #include "common/ieee802_11_defs.h" 20 #include "config.h" 21 #include "wpa_supplicant_i.h" 22 #include "driver_i.h" 23 #include "mlme.h" 24 #include "wps_supplicant.h" 25 #include "p2p_supplicant.h" 26 #include "p2p/p2p.h" 27 #include "notify.h" 28 #include "bss.h" 29 #include "scan.h" 30 31 32 static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) 33 { 34 struct wpa_ssid *ssid; 35 union wpa_event_data data; 36 37 ssid = wpa_supplicant_get_ssid(wpa_s); 38 if (ssid == NULL) 39 return; 40 41 if (wpa_s->current_ssid == NULL) { 42 wpa_s->current_ssid = ssid; 43 if (wpa_s->current_ssid != NULL) 44 wpas_notify_network_changed(wpa_s); 45 } 46 wpa_supplicant_initiate_eapol(wpa_s); 47 wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured " 48 "network - generating associated event"); 49 os_memset(&data, 0, sizeof(data)); 50 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); 51 } 52 53 54 #ifdef CONFIG_WPS 55 static int wpas_wps_in_use(struct wpa_config *conf, 56 enum wps_request_type *req_type) 57 { 58 struct wpa_ssid *ssid; 59 int wps = 0; 60 61 for (ssid = conf->ssid; ssid; ssid = ssid->next) { 62 if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) 63 continue; 64 65 wps = 1; 66 *req_type = wpas_wps_get_req_type(ssid); 67 if (!ssid->eap.phase1) 68 continue; 69 70 if (os_strstr(ssid->eap.phase1, "pbc=1")) 71 return 2; 72 } 73 74 return wps; 75 } 76 #endif /* CONFIG_WPS */ 77 78 79 int wpa_supplicant_enabled_networks(struct wpa_config *conf) 80 { 81 struct wpa_ssid *ssid = conf->ssid; 82 int count = 0; 83 while (ssid) { 84 if (!ssid->disabled) 85 count++; 86 ssid = ssid->next; 87 } 88 return count; 89 } 90 91 92 static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, 93 struct wpa_ssid *ssid) 94 { 95 while (ssid) { 96 if (!ssid->disabled) 97 break; 98 ssid = ssid->next; 99 } 100 101 /* ap_scan=2 mode - try to associate with each SSID. */ 102 if (ssid == NULL) { 103 wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached " 104 "end of scan list - go back to beginning"); 105 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 106 wpa_supplicant_req_scan(wpa_s, 0, 0); 107 return; 108 } 109 if (ssid->next) { 110 /* Continue from the next SSID on the next attempt. */ 111 wpa_s->prev_scan_ssid = ssid; 112 } else { 113 /* Start from the beginning of the SSID list. */ 114 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 115 } 116 wpa_supplicant_associate(wpa_s, NULL, ssid); 117 } 118 119 120 static int int_array_len(const int *a) 121 { 122 int i; 123 for (i = 0; a && a[i]; i++) 124 ; 125 return i; 126 } 127 128 129 static void int_array_concat(int **res, const int *a) 130 { 131 int reslen, alen, i; 132 int *n; 133 134 reslen = int_array_len(*res); 135 alen = int_array_len(a); 136 137 n = os_realloc(*res, (reslen + alen + 1) * sizeof(int)); 138 if (n == NULL) { 139 os_free(*res); 140 *res = NULL; 141 return; 142 } 143 for (i = 0; i <= alen; i++) 144 n[reslen + i] = a[i]; 145 *res = n; 146 } 147 148 149 static int freq_cmp(const void *a, const void *b) 150 { 151 int _a = *(int *) a; 152 int _b = *(int *) b; 153 154 if (_a == 0) 155 return 1; 156 if (_b == 0) 157 return -1; 158 return _a - _b; 159 } 160 161 162 static void int_array_sort_unique(int *a) 163 { 164 int alen; 165 int i, j; 166 167 if (a == NULL) 168 return; 169 170 alen = int_array_len(a); 171 qsort(a, alen, sizeof(int), freq_cmp); 172 173 i = 0; 174 j = 1; 175 while (a[i] && a[j]) { 176 if (a[i] == a[j]) { 177 j++; 178 continue; 179 } 180 a[++i] = a[j++]; 181 } 182 if (a[i]) 183 i++; 184 a[i] = 0; 185 } 186 187 188 int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, 189 struct wpa_driver_scan_params *params) 190 { 191 int ret; 192 193 wpa_supplicant_notify_scanning(wpa_s, 1); 194 195 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) 196 ret = ieee80211_sta_req_scan(wpa_s, params); 197 else 198 ret = wpa_drv_scan(wpa_s, params); 199 200 if (ret) { 201 wpa_supplicant_notify_scanning(wpa_s, 0); 202 wpas_notify_scan_done(wpa_s, 0); 203 } else 204 wpa_s->scan_runs++; 205 206 return ret; 207 } 208 209 210 static struct wpa_driver_scan_filter * 211 wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids) 212 { 213 struct wpa_driver_scan_filter *ssids; 214 struct wpa_ssid *ssid; 215 size_t count; 216 217 *num_ssids = 0; 218 if (!conf->filter_ssids) 219 return NULL; 220 221 for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) { 222 if (ssid->ssid && ssid->ssid_len) 223 count++; 224 } 225 if (count == 0) 226 return NULL; 227 ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter)); 228 if (ssids == NULL) 229 return NULL; 230 231 for (ssid = conf->ssid; ssid; ssid = ssid->next) { 232 if (!ssid->ssid || !ssid->ssid_len) 233 continue; 234 os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len); 235 ssids[*num_ssids].ssid_len = ssid->ssid_len; 236 (*num_ssids)++; 237 } 238 239 return ssids; 240 } 241 242 243 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) 244 { 245 struct wpa_supplicant *wpa_s = eloop_ctx; 246 struct wpa_ssid *ssid; 247 int scan_req = 0, ret; 248 struct wpabuf *wps_ie = NULL; 249 #ifdef CONFIG_WPS 250 int wps = 0; 251 enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO; 252 #endif /* CONFIG_WPS */ 253 struct wpa_driver_scan_params params; 254 size_t max_ssids; 255 enum wpa_states prev_state; 256 257 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 258 wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); 259 return; 260 } 261 262 if (wpa_s->disconnected && !wpa_s->scan_req) { 263 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 264 return; 265 } 266 267 if (!wpa_supplicant_enabled_networks(wpa_s->conf) && 268 !wpa_s->scan_req) { 269 wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); 270 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 271 return; 272 } 273 274 if (wpa_s->conf->ap_scan != 0 && 275 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) { 276 wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - " 277 "overriding ap_scan configuration"); 278 wpa_s->conf->ap_scan = 0; 279 wpas_notify_ap_scan_changed(wpa_s); 280 } 281 282 if (wpa_s->conf->ap_scan == 0) { 283 wpa_supplicant_gen_assoc_event(wpa_s); 284 return; 285 } 286 287 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) || 288 wpa_s->conf->ap_scan == 2) 289 max_ssids = 1; 290 else { 291 max_ssids = wpa_s->max_scan_ssids; 292 if (max_ssids > WPAS_MAX_SCAN_SSIDS) 293 max_ssids = WPAS_MAX_SCAN_SSIDS; 294 } 295 296 #ifdef CONFIG_WPS 297 wps = wpas_wps_in_use(wpa_s->conf, &req_type); 298 #endif /* CONFIG_WPS */ 299 300 scan_req = wpa_s->scan_req; 301 wpa_s->scan_req = 0; 302 303 os_memset(¶ms, 0, sizeof(params)); 304 305 prev_state = wpa_s->wpa_state; 306 if (wpa_s->wpa_state == WPA_DISCONNECTED || 307 wpa_s->wpa_state == WPA_INACTIVE) 308 wpa_supplicant_set_state(wpa_s, WPA_SCANNING); 309 310 if (scan_req != 2 && wpa_s->connect_without_scan) { 311 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 312 if (ssid == wpa_s->connect_without_scan) 313 break; 314 } 315 wpa_s->connect_without_scan = NULL; 316 if (ssid) { 317 wpa_printf(MSG_DEBUG, "Start a pre-selected network " 318 "without scan step"); 319 wpa_supplicant_associate(wpa_s, NULL, ssid); 320 return; 321 } 322 } 323 324 /* Find the starting point from which to continue scanning */ 325 ssid = wpa_s->conf->ssid; 326 if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) { 327 while (ssid) { 328 if (ssid == wpa_s->prev_scan_ssid) { 329 ssid = ssid->next; 330 break; 331 } 332 ssid = ssid->next; 333 } 334 } 335 336 if (scan_req != 2 && wpa_s->conf->ap_scan == 2) { 337 wpa_s->connect_without_scan = NULL; 338 wpa_supplicant_assoc_try(wpa_s, ssid); 339 return; 340 #ifndef ANDROID 341 } else if (wpa_s->conf->ap_scan == 2) { 342 /* 343 * User-initiated scan request in ap_scan == 2; scan with 344 * wildcard SSID. 345 */ 346 ssid = NULL; 347 #endif 348 } else { 349 struct wpa_ssid *start = ssid, *tssid; 350 int freqs_set = 0; 351 if (ssid == NULL && max_ssids > 1) 352 ssid = wpa_s->conf->ssid; 353 while (ssid) { 354 if (!ssid->disabled && ssid->scan_ssid) { 355 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", 356 ssid->ssid, ssid->ssid_len); 357 params.ssids[params.num_ssids].ssid = 358 ssid->ssid; 359 params.ssids[params.num_ssids].ssid_len = 360 ssid->ssid_len; 361 params.num_ssids++; 362 if (params.num_ssids + 1 >= max_ssids) 363 break; 364 } 365 ssid = ssid->next; 366 if (ssid == start) 367 break; 368 if (ssid == NULL && max_ssids > 1 && 369 start != wpa_s->conf->ssid) 370 ssid = wpa_s->conf->ssid; 371 } 372 373 for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { 374 if (tssid->disabled) 375 continue; 376 if ((params.freqs || !freqs_set) && tssid->scan_freq) { 377 int_array_concat(¶ms.freqs, 378 tssid->scan_freq); 379 } else { 380 os_free(params.freqs); 381 params.freqs = NULL; 382 } 383 freqs_set = 1; 384 } 385 int_array_sort_unique(params.freqs); 386 } 387 388 if (ssid) { 389 wpa_s->prev_scan_ssid = ssid; 390 if (max_ssids > 1) { 391 wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in " 392 "the scan request"); 393 params.num_ssids++; 394 } 395 wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for specific " 396 "SSID(s)"); 397 } else { 398 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 399 params.num_ssids++; 400 wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard " 401 "SSID"); 402 } 403 404 #ifdef CONFIG_P2P 405 wpa_s->wps->dev.p2p = 1; 406 if (!wps) { 407 wps = 1; 408 req_type = WPS_REQ_ENROLLEE_INFO; 409 } 410 411 if (params.freqs == NULL && wpa_s->p2p_in_provisioning && 412 wpa_s->go_params) { 413 /* Optimize provisioning state scan based on GO information */ 414 if (wpa_s->p2p_in_provisioning < 5 && 415 wpa_s->go_params->freq > 0) { 416 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO " 417 "preferred frequency %d MHz", 418 wpa_s->go_params->freq); 419 params.freqs = os_zalloc(2 * sizeof(int)); 420 if (params.freqs) 421 params.freqs[0] = wpa_s->go_params->freq; 422 } else if (wpa_s->p2p_in_provisioning < 8 && 423 wpa_s->go_params->freq_list[0]) { 424 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common " 425 "channels"); 426 int_array_concat(¶ms.freqs, 427 wpa_s->go_params->freq_list); 428 if (params.freqs) 429 int_array_sort_unique(params.freqs); 430 } 431 wpa_s->p2p_in_provisioning++; 432 } 433 #endif /* CONFIG_P2P */ 434 435 #ifdef CONFIG_WPS 436 if (params.freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) { 437 /* 438 * Optimize post-provisioning scan based on channel used 439 * during provisioning. 440 */ 441 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz " 442 "that was used during provisioning", wpa_s->wps_freq); 443 params.freqs = os_zalloc(2 * sizeof(int)); 444 if (params.freqs) 445 params.freqs[0] = wpa_s->wps_freq; 446 wpa_s->after_wps--; 447 } 448 449 if (wps) { 450 wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev, 451 wpa_s->wps->uuid, req_type, 452 0, NULL); 453 if (wps_ie) { 454 params.extra_ies = wpabuf_head(wps_ie); 455 params.extra_ies_len = wpabuf_len(wps_ie); 456 } 457 } 458 #endif /* CONFIG_WPS */ 459 460 #ifdef CONFIG_P2P 461 if (wps_ie) { 462 if (wpabuf_resize(&wps_ie, 100) == 0) { 463 wpas_p2p_scan_ie(wpa_s, wps_ie); 464 params.extra_ies = wpabuf_head(wps_ie); 465 params.extra_ies_len = wpabuf_len(wps_ie); 466 } 467 } 468 #endif /* CONFIG_P2P */ 469 470 if (params.freqs == NULL && wpa_s->next_scan_freqs) { 471 wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously " 472 "generated frequency list"); 473 params.freqs = wpa_s->next_scan_freqs; 474 } else 475 os_free(wpa_s->next_scan_freqs); 476 wpa_s->next_scan_freqs = NULL; 477 478 params.filter_ssids = wpa_supplicant_build_filter_ssids( 479 wpa_s->conf, ¶ms.num_filter_ssids); 480 481 ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms); 482 483 wpabuf_free(wps_ie); 484 os_free(params.freqs); 485 os_free(params.filter_ssids); 486 487 if (ret) { 488 wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan"); 489 if (prev_state != wpa_s->wpa_state) 490 wpa_supplicant_set_state(wpa_s, prev_state); 491 wpa_supplicant_req_scan(wpa_s, 1, 0); 492 } 493 } 494 495 496 /** 497 * wpa_supplicant_req_scan - Schedule a scan for neighboring access points 498 * @wpa_s: Pointer to wpa_supplicant data 499 * @sec: Number of seconds after which to scan 500 * @usec: Number of microseconds after which to scan 501 * 502 * This function is used to schedule a scan for neighboring access points after 503 * the specified time. 504 */ 505 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) 506 { 507 /* If there's at least one network that should be specifically scanned 508 * then don't cancel the scan and reschedule. Some drivers do 509 * background scanning which generates frequent scan results, and that 510 * causes the specific SSID scan to get continually pushed back and 511 * never happen, which causes hidden APs to never get probe-scanned. 512 */ 513 if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) && 514 wpa_s->conf->ap_scan == 1) { 515 struct wpa_ssid *ssid = wpa_s->conf->ssid; 516 517 while (ssid) { 518 if (!ssid->disabled && ssid->scan_ssid) 519 break; 520 ssid = ssid->next; 521 } 522 if (ssid) { 523 wpa_dbg(wpa_s, MSG_DEBUG, "Not rescheduling scan to " 524 "ensure that specific SSID scans occur"); 525 return; 526 } 527 } 528 529 wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", 530 sec, usec); 531 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 532 eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); 533 } 534 535 536 /** 537 * wpa_supplicant_cancel_scan - Cancel a scheduled scan request 538 * @wpa_s: Pointer to wpa_supplicant data 539 * 540 * This function is used to cancel a scan request scheduled with 541 * wpa_supplicant_req_scan(). 542 */ 543 void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) 544 { 545 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request"); 546 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 547 wpa_supplicant_notify_scanning(wpa_s, 0); 548 } 549 550 551 void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, 552 int scanning) 553 { 554 if (wpa_s->scanning != scanning) { 555 wpa_s->scanning = scanning; 556 wpas_notify_scanning(wpa_s); 557 } 558 } 559 560 561 static int wpa_scan_get_max_rate(const struct wpa_scan_res *res) 562 { 563 int rate = 0; 564 const u8 *ie; 565 int i; 566 567 ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); 568 for (i = 0; ie && i < ie[1]; i++) { 569 if ((ie[i + 2] & 0x7f) > rate) 570 rate = ie[i + 2] & 0x7f; 571 } 572 573 ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); 574 for (i = 0; ie && i < ie[1]; i++) { 575 if ((ie[i + 2] & 0x7f) > rate) 576 rate = ie[i + 2] & 0x7f; 577 } 578 579 return rate; 580 } 581 582 583 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) 584 { 585 const u8 *end, *pos; 586 587 pos = (const u8 *) (res + 1); 588 end = pos + res->ie_len; 589 590 while (pos + 1 < end) { 591 if (pos + 2 + pos[1] > end) 592 break; 593 if (pos[0] == ie) 594 return pos; 595 pos += 2 + pos[1]; 596 } 597 598 return NULL; 599 } 600 601 602 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, 603 u32 vendor_type) 604 { 605 const u8 *end, *pos; 606 607 pos = (const u8 *) (res + 1); 608 end = pos + res->ie_len; 609 610 while (pos + 1 < end) { 611 if (pos + 2 + pos[1] > end) 612 break; 613 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 614 vendor_type == WPA_GET_BE32(&pos[2])) 615 return pos; 616 pos += 2 + pos[1]; 617 } 618 619 return NULL; 620 } 621 622 623 struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, 624 u32 vendor_type) 625 { 626 struct wpabuf *buf; 627 const u8 *end, *pos; 628 629 buf = wpabuf_alloc(res->ie_len); 630 if (buf == NULL) 631 return NULL; 632 633 pos = (const u8 *) (res + 1); 634 end = pos + res->ie_len; 635 636 while (pos + 1 < end) { 637 if (pos + 2 + pos[1] > end) 638 break; 639 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 640 vendor_type == WPA_GET_BE32(&pos[2])) 641 wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); 642 pos += 2 + pos[1]; 643 } 644 645 if (wpabuf_len(buf) == 0) { 646 wpabuf_free(buf); 647 buf = NULL; 648 } 649 650 return buf; 651 } 652 653 654 struct wpabuf * wpa_scan_get_vendor_ie_multi_beacon( 655 const struct wpa_scan_res *res, u32 vendor_type) 656 { 657 struct wpabuf *buf; 658 const u8 *end, *pos; 659 660 if (res->beacon_ie_len == 0) 661 return NULL; 662 buf = wpabuf_alloc(res->beacon_ie_len); 663 if (buf == NULL) 664 return NULL; 665 666 pos = (const u8 *) (res + 1); 667 pos += res->ie_len; 668 end = pos + res->beacon_ie_len; 669 670 while (pos + 1 < end) { 671 if (pos + 2 + pos[1] > end) 672 break; 673 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 674 vendor_type == WPA_GET_BE32(&pos[2])) 675 wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); 676 pos += 2 + pos[1]; 677 } 678 679 if (wpabuf_len(buf) == 0) { 680 wpabuf_free(buf); 681 buf = NULL; 682 } 683 684 return buf; 685 } 686 687 688 /* Compare function for sorting scan results. Return >0 if @b is considered 689 * better. */ 690 static int wpa_scan_result_compar(const void *a, const void *b) 691 { 692 struct wpa_scan_res **_wa = (void *) a; 693 struct wpa_scan_res **_wb = (void *) b; 694 struct wpa_scan_res *wa = *_wa; 695 struct wpa_scan_res *wb = *_wb; 696 int wpa_a, wpa_b, maxrate_a, maxrate_b; 697 698 /* WPA/WPA2 support preferred */ 699 wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || 700 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; 701 wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || 702 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; 703 704 if (wpa_b && !wpa_a) 705 return 1; 706 if (!wpa_b && wpa_a) 707 return -1; 708 709 /* privacy support preferred */ 710 if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && 711 (wb->caps & IEEE80211_CAP_PRIVACY)) 712 return 1; 713 if ((wa->caps & IEEE80211_CAP_PRIVACY) && 714 (wb->caps & IEEE80211_CAP_PRIVACY) == 0) 715 return -1; 716 717 /* best/max rate preferred if signal level close enough XXX */ 718 if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) || 719 (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { 720 maxrate_a = wpa_scan_get_max_rate(wa); 721 maxrate_b = wpa_scan_get_max_rate(wb); 722 if (maxrate_a != maxrate_b) 723 return maxrate_b - maxrate_a; 724 } 725 726 /* use freq for channel preference */ 727 728 /* all things being equal, use signal level; if signal levels are 729 * identical, use quality values since some drivers may only report 730 * that value and leave the signal level zero */ 731 if (wb->level == wa->level) 732 return wb->qual - wa->qual; 733 return wb->level - wa->level; 734 } 735 736 737 #ifdef CONFIG_WPS 738 /* Compare function for sorting scan results when searching a WPS AP for 739 * provisioning. Return >0 if @b is considered better. */ 740 static int wpa_scan_result_wps_compar(const void *a, const void *b) 741 { 742 struct wpa_scan_res **_wa = (void *) a; 743 struct wpa_scan_res **_wb = (void *) b; 744 struct wpa_scan_res *wa = *_wa; 745 struct wpa_scan_res *wb = *_wb; 746 int uses_wps_a, uses_wps_b; 747 struct wpabuf *wps_a, *wps_b; 748 int res; 749 750 /* Optimization - check WPS IE existence before allocated memory and 751 * doing full reassembly. */ 752 uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL; 753 uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL; 754 if (uses_wps_a && !uses_wps_b) 755 return -1; 756 if (!uses_wps_a && uses_wps_b) 757 return 1; 758 759 if (uses_wps_a && uses_wps_b) { 760 wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE); 761 wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE); 762 res = wps_ap_priority_compar(wps_a, wps_b); 763 wpabuf_free(wps_a); 764 wpabuf_free(wps_b); 765 if (res) 766 return res; 767 } 768 769 /* 770 * Do not use current AP security policy as a sorting criteria during 771 * WPS provisioning step since the AP may get reconfigured at the 772 * completion of provisioning. 773 */ 774 775 /* all things being equal, use signal level; if signal levels are 776 * identical, use quality values since some drivers may only report 777 * that value and leave the signal level zero */ 778 if (wb->level == wa->level) 779 return wb->qual - wa->qual; 780 return wb->level - wa->level; 781 } 782 #endif /* CONFIG_WPS */ 783 784 785 /** 786 * wpa_supplicant_get_scan_results - Get scan results 787 * @wpa_s: Pointer to wpa_supplicant data 788 * @info: Information about what was scanned or %NULL if not available 789 * @new_scan: Whether a new scan was performed 790 * Returns: Scan results, %NULL on failure 791 * 792 * This function request the current scan results from the driver and updates 793 * the local BSS list wpa_s->bss. The caller is responsible for freeing the 794 * results with wpa_scan_results_free(). 795 */ 796 struct wpa_scan_results * 797 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, 798 struct scan_info *info, int new_scan) 799 { 800 struct wpa_scan_results *scan_res; 801 size_t i; 802 int (*compar)(const void *, const void *) = wpa_scan_result_compar; 803 804 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) 805 scan_res = ieee80211_sta_get_scan_results(wpa_s); 806 else 807 scan_res = wpa_drv_get_scan_results2(wpa_s); 808 if (scan_res == NULL) { 809 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results"); 810 return NULL; 811 } 812 813 #ifdef CONFIG_WPS 814 if (wpas_wps_in_progress(wpa_s)) { 815 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS " 816 "provisioning rules"); 817 compar = wpa_scan_result_wps_compar; 818 } 819 #endif /* CONFIG_WPS */ 820 821 qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), 822 compar); 823 824 wpa_bss_update_start(wpa_s); 825 for (i = 0; i < scan_res->num; i++) 826 wpa_bss_update_scan_res(wpa_s, scan_res->res[i]); 827 wpa_bss_update_end(wpa_s, info, new_scan); 828 829 return scan_res; 830 } 831 832 833 int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) 834 { 835 struct wpa_scan_results *scan_res; 836 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); 837 if (scan_res == NULL) 838 return -1; 839 wpa_scan_results_free(scan_res); 840 841 return 0; 842 } 843 844 845 void wpa_scan_results_free(struct wpa_scan_results *res) 846 { 847 size_t i; 848 849 if (res == NULL) 850 return; 851 852 for (i = 0; i < res->num; i++) 853 os_free(res->res[i]); 854 os_free(res->res); 855 os_free(res); 856 } 857