1 /* 2 * WPA Supplicant - Scanning 3 * Copyright (c) 2003-2010, Jouni Malinen <j@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 "notify.h" 26 #include "bss.h" 27 #include "scan.h" 28 29 30 static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) 31 { 32 struct wpa_ssid *ssid; 33 union wpa_event_data data; 34 35 ssid = wpa_supplicant_get_ssid(wpa_s); 36 if (ssid == NULL) 37 return; 38 39 if (wpa_s->current_ssid == NULL) { 40 wpa_s->current_ssid = ssid; 41 if (wpa_s->current_ssid != NULL) 42 wpas_notify_network_changed(wpa_s); 43 } 44 wpa_supplicant_initiate_eapol(wpa_s); 45 wpa_printf(MSG_DEBUG, "Already associated with a configured network - " 46 "generating associated event"); 47 os_memset(&data, 0, sizeof(data)); 48 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); 49 } 50 51 52 #ifdef CONFIG_WPS 53 static int wpas_wps_in_use(struct wpa_config *conf, 54 enum wps_request_type *req_type) 55 { 56 struct wpa_ssid *ssid; 57 int wps = 0; 58 59 for (ssid = conf->ssid; ssid; ssid = ssid->next) { 60 if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) 61 continue; 62 63 wps = 1; 64 *req_type = wpas_wps_get_req_type(ssid); 65 if (!ssid->eap.phase1) 66 continue; 67 68 if (os_strstr(ssid->eap.phase1, "pbc=1")) 69 return 2; 70 } 71 72 return wps; 73 } 74 #endif /* CONFIG_WPS */ 75 76 77 int wpa_supplicant_enabled_networks(struct wpa_config *conf) 78 { 79 struct wpa_ssid *ssid = conf->ssid; 80 while (ssid) { 81 if (!ssid->disabled) 82 return 1; 83 ssid = ssid->next; 84 } 85 return 0; 86 } 87 88 89 static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, 90 struct wpa_ssid *ssid) 91 { 92 while (ssid) { 93 if (!ssid->disabled) 94 break; 95 ssid = ssid->next; 96 } 97 98 /* ap_scan=2 mode - try to associate with each SSID. */ 99 if (ssid == NULL) { 100 wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached " 101 "end of scan list - go back to beginning"); 102 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 103 wpa_supplicant_req_scan(wpa_s, 0, 0); 104 return; 105 } 106 if (ssid->next) { 107 /* Continue from the next SSID on the next attempt. */ 108 wpa_s->prev_scan_ssid = ssid; 109 } else { 110 /* Start from the beginning of the SSID list. */ 111 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 112 } 113 wpa_supplicant_associate(wpa_s, NULL, ssid); 114 } 115 116 117 static int int_array_len(const int *a) 118 { 119 int i; 120 for (i = 0; a && a[i]; i++) 121 ; 122 return i; 123 } 124 125 126 static void int_array_concat(int **res, const int *a) 127 { 128 int reslen, alen, i; 129 int *n; 130 131 reslen = int_array_len(*res); 132 alen = int_array_len(a); 133 134 n = os_realloc(*res, (reslen + alen + 1) * sizeof(int)); 135 if (n == NULL) { 136 os_free(*res); 137 *res = NULL; 138 return; 139 } 140 for (i = 0; i <= alen; i++) 141 n[reslen + i] = a[i]; 142 *res = n; 143 } 144 145 146 static int freq_cmp(const void *a, const void *b) 147 { 148 int _a = *(int *) a; 149 int _b = *(int *) b; 150 151 if (_a == 0) 152 return 1; 153 if (_b == 0) 154 return -1; 155 return _a - _b; 156 } 157 158 159 static void int_array_sort_unique(int *a) 160 { 161 int alen; 162 int i, j; 163 164 if (a == NULL) 165 return; 166 167 alen = int_array_len(a); 168 qsort(a, alen, sizeof(int), freq_cmp); 169 170 i = 0; 171 j = 1; 172 while (a[i] && a[j]) { 173 if (a[i] == a[j]) { 174 j++; 175 continue; 176 } 177 a[++i] = a[j++]; 178 } 179 if (a[i]) 180 i++; 181 a[i] = 0; 182 } 183 184 185 int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, 186 struct wpa_driver_scan_params *params) 187 { 188 int ret; 189 190 wpa_supplicant_notify_scanning(wpa_s, 1); 191 192 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) 193 ret = ieee80211_sta_req_scan(wpa_s, params); 194 else 195 ret = wpa_drv_scan(wpa_s, params); 196 197 if (ret) { 198 wpa_supplicant_notify_scanning(wpa_s, 0); 199 wpas_notify_scan_done(wpa_s, 0); 200 } else 201 wpa_s->scan_runs++; 202 203 return ret; 204 } 205 206 207 static struct wpa_driver_scan_filter * 208 wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids) 209 { 210 struct wpa_driver_scan_filter *ssids; 211 struct wpa_ssid *ssid; 212 size_t count; 213 214 *num_ssids = 0; 215 if (!conf->filter_ssids) 216 return NULL; 217 218 for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) { 219 if (ssid->ssid && ssid->ssid_len) 220 count++; 221 } 222 if (count == 0) 223 return NULL; 224 ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter)); 225 if (ssids == NULL) 226 return NULL; 227 228 for (ssid = conf->ssid; ssid; ssid = ssid->next) { 229 if (!ssid->ssid || !ssid->ssid_len) 230 continue; 231 os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len); 232 ssids[*num_ssids].ssid_len = ssid->ssid_len; 233 (*num_ssids)++; 234 } 235 236 return ssids; 237 } 238 239 240 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) 241 { 242 struct wpa_supplicant *wpa_s = eloop_ctx; 243 struct wpa_ssid *ssid; 244 int scan_req = 0, ret; 245 struct wpabuf *wps_ie = NULL; 246 #ifdef CONFIG_WPS 247 int wps = 0; 248 enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO; 249 #endif /* CONFIG_WPS */ 250 struct wpa_driver_scan_params params; 251 size_t max_ssids; 252 enum wpa_states prev_state; 253 254 if (wpa_s->disconnected && !wpa_s->scan_req) { 255 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 256 return; 257 } 258 259 if (!wpa_supplicant_enabled_networks(wpa_s->conf) && 260 !wpa_s->scan_req) { 261 wpa_printf(MSG_DEBUG, "No enabled networks - do not scan"); 262 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 263 return; 264 } 265 266 if (wpa_s->conf->ap_scan != 0 && 267 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) { 268 wpa_printf(MSG_DEBUG, "Using wired authentication - " 269 "overriding ap_scan configuration"); 270 wpa_s->conf->ap_scan = 0; 271 wpas_notify_ap_scan_changed(wpa_s); 272 } 273 274 if (wpa_s->conf->ap_scan == 0) { 275 wpa_supplicant_gen_assoc_event(wpa_s); 276 return; 277 } 278 279 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) || 280 wpa_s->conf->ap_scan == 2) 281 max_ssids = 1; 282 else { 283 max_ssids = wpa_s->max_scan_ssids; 284 if (max_ssids > WPAS_MAX_SCAN_SSIDS) 285 max_ssids = WPAS_MAX_SCAN_SSIDS; 286 } 287 288 #ifdef CONFIG_WPS 289 wps = wpas_wps_in_use(wpa_s->conf, &req_type); 290 #endif /* CONFIG_WPS */ 291 292 scan_req = wpa_s->scan_req; 293 wpa_s->scan_req = 0; 294 295 os_memset(¶ms, 0, sizeof(params)); 296 297 prev_state = wpa_s->wpa_state; 298 if (wpa_s->wpa_state == WPA_DISCONNECTED || 299 wpa_s->wpa_state == WPA_INACTIVE) 300 wpa_supplicant_set_state(wpa_s, WPA_SCANNING); 301 302 /* Find the starting point from which to continue scanning */ 303 ssid = wpa_s->conf->ssid; 304 if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) { 305 while (ssid) { 306 if (ssid == wpa_s->prev_scan_ssid) { 307 ssid = ssid->next; 308 break; 309 } 310 ssid = ssid->next; 311 } 312 } 313 314 if (scan_req != 2 && (wpa_s->conf->ap_scan == 2 || 315 wpa_s->connect_without_scan)) { 316 wpa_s->connect_without_scan = 0; 317 wpa_supplicant_assoc_try(wpa_s, ssid); 318 return; 319 } else if (wpa_s->conf->ap_scan == 2) { 320 /* 321 * User-initiated scan request in ap_scan == 2; scan with 322 * wildcard SSID. 323 */ 324 ssid = NULL; 325 } else { 326 struct wpa_ssid *start = ssid, *tssid; 327 int freqs_set = 0; 328 if (ssid == NULL && max_ssids > 1) 329 ssid = wpa_s->conf->ssid; 330 while (ssid) { 331 if (!ssid->disabled && ssid->scan_ssid) { 332 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", 333 ssid->ssid, ssid->ssid_len); 334 params.ssids[params.num_ssids].ssid = 335 ssid->ssid; 336 params.ssids[params.num_ssids].ssid_len = 337 ssid->ssid_len; 338 params.num_ssids++; 339 if (params.num_ssids + 1 >= max_ssids) 340 break; 341 } 342 ssid = ssid->next; 343 if (ssid == start) 344 break; 345 if (ssid == NULL && max_ssids > 1 && 346 start != wpa_s->conf->ssid) 347 ssid = wpa_s->conf->ssid; 348 } 349 350 for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { 351 if (tssid->disabled) 352 continue; 353 if ((params.freqs || !freqs_set) && tssid->scan_freq) { 354 int_array_concat(¶ms.freqs, 355 tssid->scan_freq); 356 } else { 357 os_free(params.freqs); 358 params.freqs = NULL; 359 } 360 freqs_set = 1; 361 } 362 int_array_sort_unique(params.freqs); 363 } 364 365 if (ssid) { 366 wpa_s->prev_scan_ssid = ssid; 367 if (max_ssids > 1) { 368 wpa_printf(MSG_DEBUG, "Include wildcard SSID in the " 369 "scan request"); 370 params.num_ssids++; 371 } 372 wpa_printf(MSG_DEBUG, "Starting AP scan for specific SSID(s)"); 373 } else { 374 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 375 params.num_ssids++; 376 wpa_printf(MSG_DEBUG, "Starting AP scan for wildcard SSID"); 377 } 378 379 #ifdef CONFIG_WPS 380 if (params.freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) { 381 /* 382 * Optimize post-provisioning scan based on channel used 383 * during provisioning. 384 */ 385 wpa_printf(MSG_DEBUG, "WPS: Scan only frequency %u MHz that " 386 "was used during provisioning", wpa_s->wps_freq); 387 params.freqs = os_zalloc(2 * sizeof(int)); 388 if (params.freqs) 389 params.freqs[0] = wpa_s->wps_freq; 390 wpa_s->after_wps--; 391 } 392 393 if (wps) { 394 wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev, 395 wpa_s->wps->uuid, req_type); 396 if (wps_ie) { 397 params.extra_ies = wpabuf_head(wps_ie); 398 params.extra_ies_len = wpabuf_len(wps_ie); 399 } 400 } 401 #endif /* CONFIG_WPS */ 402 403 params.filter_ssids = wpa_supplicant_build_filter_ssids( 404 wpa_s->conf, ¶ms.num_filter_ssids); 405 406 ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms); 407 408 wpabuf_free(wps_ie); 409 os_free(params.freqs); 410 os_free(params.filter_ssids); 411 412 if (ret) { 413 wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); 414 if (prev_state != wpa_s->wpa_state) 415 wpa_supplicant_set_state(wpa_s, prev_state); 416 wpa_supplicant_req_scan(wpa_s, 1, 0); 417 } 418 } 419 420 421 /** 422 * wpa_supplicant_req_scan - Schedule a scan for neighboring access points 423 * @wpa_s: Pointer to wpa_supplicant data 424 * @sec: Number of seconds after which to scan 425 * @usec: Number of microseconds after which to scan 426 * 427 * This function is used to schedule a scan for neighboring access points after 428 * the specified time. 429 */ 430 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) 431 { 432 /* If there's at least one network that should be specifically scanned 433 * then don't cancel the scan and reschedule. Some drivers do 434 * background scanning which generates frequent scan results, and that 435 * causes the specific SSID scan to get continually pushed back and 436 * never happen, which causes hidden APs to never get probe-scanned. 437 */ 438 if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) && 439 wpa_s->conf->ap_scan == 1) { 440 struct wpa_ssid *ssid = wpa_s->conf->ssid; 441 442 while (ssid) { 443 if (!ssid->disabled && ssid->scan_ssid) 444 break; 445 ssid = ssid->next; 446 } 447 if (ssid) { 448 wpa_msg(wpa_s, MSG_DEBUG, "Not rescheduling scan to " 449 "ensure that specific SSID scans occur"); 450 return; 451 } 452 } 453 454 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", 455 sec, usec); 456 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 457 eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); 458 } 459 460 461 /** 462 * wpa_supplicant_cancel_scan - Cancel a scheduled scan request 463 * @wpa_s: Pointer to wpa_supplicant data 464 * 465 * This function is used to cancel a scan request scheduled with 466 * wpa_supplicant_req_scan(). 467 */ 468 void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) 469 { 470 wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request"); 471 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 472 } 473 474 475 void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, 476 int scanning) 477 { 478 if (wpa_s->scanning != scanning) { 479 wpa_s->scanning = scanning; 480 wpas_notify_scanning(wpa_s); 481 } 482 } 483 484 485 static int wpa_scan_get_max_rate(const struct wpa_scan_res *res) 486 { 487 int rate = 0; 488 const u8 *ie; 489 int i; 490 491 ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); 492 for (i = 0; ie && i < ie[1]; i++) { 493 if ((ie[i + 2] & 0x7f) > rate) 494 rate = ie[i + 2] & 0x7f; 495 } 496 497 ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); 498 for (i = 0; ie && i < ie[1]; i++) { 499 if ((ie[i + 2] & 0x7f) > rate) 500 rate = ie[i + 2] & 0x7f; 501 } 502 503 return rate; 504 } 505 506 507 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) 508 { 509 const u8 *end, *pos; 510 511 pos = (const u8 *) (res + 1); 512 end = pos + res->ie_len; 513 514 while (pos + 1 < end) { 515 if (pos + 2 + pos[1] > end) 516 break; 517 if (pos[0] == ie) 518 return pos; 519 pos += 2 + pos[1]; 520 } 521 522 return NULL; 523 } 524 525 526 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, 527 u32 vendor_type) 528 { 529 const u8 *end, *pos; 530 531 pos = (const u8 *) (res + 1); 532 end = pos + res->ie_len; 533 534 while (pos + 1 < end) { 535 if (pos + 2 + pos[1] > end) 536 break; 537 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 538 vendor_type == WPA_GET_BE32(&pos[2])) 539 return pos; 540 pos += 2 + pos[1]; 541 } 542 543 return NULL; 544 } 545 546 547 struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, 548 u32 vendor_type) 549 { 550 struct wpabuf *buf; 551 const u8 *end, *pos; 552 553 buf = wpabuf_alloc(res->ie_len); 554 if (buf == NULL) 555 return NULL; 556 557 pos = (const u8 *) (res + 1); 558 end = pos + res->ie_len; 559 560 while (pos + 1 < end) { 561 if (pos + 2 + pos[1] > end) 562 break; 563 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 564 vendor_type == WPA_GET_BE32(&pos[2])) 565 wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); 566 pos += 2 + pos[1]; 567 } 568 569 if (wpabuf_len(buf) == 0) { 570 wpabuf_free(buf); 571 buf = NULL; 572 } 573 574 return buf; 575 } 576 577 578 /* Compare function for sorting scan results. Return >0 if @b is considered 579 * better. */ 580 static int wpa_scan_result_compar(const void *a, const void *b) 581 { 582 struct wpa_scan_res **_wa = (void *) a; 583 struct wpa_scan_res **_wb = (void *) b; 584 struct wpa_scan_res *wa = *_wa; 585 struct wpa_scan_res *wb = *_wb; 586 int wpa_a, wpa_b, maxrate_a, maxrate_b; 587 588 /* WPA/WPA2 support preferred */ 589 wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || 590 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; 591 wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || 592 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; 593 594 if (wpa_b && !wpa_a) 595 return 1; 596 if (!wpa_b && wpa_a) 597 return -1; 598 599 /* privacy support preferred */ 600 if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && 601 (wb->caps & IEEE80211_CAP_PRIVACY)) 602 return 1; 603 if ((wa->caps & IEEE80211_CAP_PRIVACY) && 604 (wb->caps & IEEE80211_CAP_PRIVACY) == 0) 605 return -1; 606 607 /* best/max rate preferred if signal level close enough XXX */ 608 if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) || 609 (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { 610 maxrate_a = wpa_scan_get_max_rate(wa); 611 maxrate_b = wpa_scan_get_max_rate(wb); 612 if (maxrate_a != maxrate_b) 613 return maxrate_b - maxrate_a; 614 } 615 616 /* use freq for channel preference */ 617 618 /* all things being equal, use signal level; if signal levels are 619 * identical, use quality values since some drivers may only report 620 * that value and leave the signal level zero */ 621 if (wb->level == wa->level) 622 return wb->qual - wa->qual; 623 return wb->level - wa->level; 624 } 625 626 627 /** 628 * wpa_supplicant_get_scan_results - Get scan results 629 * @wpa_s: Pointer to wpa_supplicant data 630 * @info: Information about what was scanned or %NULL if not available 631 * @new_scan: Whether a new scan was performed 632 * Returns: Scan results, %NULL on failure 633 * 634 * This function request the current scan results from the driver and updates 635 * the local BSS list wpa_s->bss. The caller is responsible for freeing the 636 * results with wpa_scan_results_free(). 637 */ 638 struct wpa_scan_results * 639 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, 640 struct scan_info *info, int new_scan) 641 { 642 struct wpa_scan_results *scan_res; 643 size_t i; 644 645 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) 646 scan_res = ieee80211_sta_get_scan_results(wpa_s); 647 else 648 scan_res = wpa_drv_get_scan_results2(wpa_s); 649 if (scan_res == NULL) { 650 wpa_printf(MSG_DEBUG, "Failed to get scan results"); 651 return NULL; 652 } 653 654 qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), 655 wpa_scan_result_compar); 656 657 wpa_bss_update_start(wpa_s); 658 for (i = 0; i < scan_res->num; i++) 659 wpa_bss_update_scan_res(wpa_s, scan_res->res[i]); 660 wpa_bss_update_end(wpa_s, info, new_scan); 661 662 return scan_res; 663 } 664 665 666 int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) 667 { 668 struct wpa_scan_results *scan_res; 669 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); 670 if (scan_res == NULL) 671 return -1; 672 wpa_scan_results_free(scan_res); 673 674 return 0; 675 } 676 677 678 void wpa_scan_results_free(struct wpa_scan_results *res) 679 { 680 size_t i; 681 682 if (res == NULL) 683 return; 684 685 for (i = 0; i < res->num; i++) 686 os_free(res->res[i]); 687 os_free(res->res); 688 os_free(res); 689 } 690