scan.c revision 20df807cb700c516ff346732f1bc8f914d0d26d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Scanning 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "mlme.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_supplicant.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_supplicant.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "notify.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bss.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "scan.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_supplicant_get_ssid(wpa_s); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL) 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->current_ssid == NULL) { 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid = ssid; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->current_ssid != NULL) 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_network_changed(wpa_s); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_initiate_eapol(wpa_s); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured " 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "network - generating associated event"); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpas_wps_in_use(struct wpa_config *conf, 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_request_type *req_type) 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wps = 0; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ssid = conf->ssid; ssid; ssid = ssid->next) { 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps = 1; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *req_type = wpas_wps_get_req_type(ssid); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->eap.phase1) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(ssid->eap.phase1, "pbc=1")) 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 2; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wps; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_enabled_networks(struct wpa_config *conf) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid = conf->ssid; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count = 0; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->disabled) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return count; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid) 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->disabled) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ap_scan=2 mode - try to associate with each SSID. */ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL) { 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached " 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "end of scan list - go back to beginning"); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->next) { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Continue from the next SSID on the next attempt. */ 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = ssid; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Start from the beginning of the SSID list. */ 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_associate(wpa_s, NULL, ssid); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int int_array_len(const int *a) 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; a && a[i]; i++) 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return i; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void int_array_concat(int **res, const int *a) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reslen, alen, i; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *n; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reslen = int_array_len(*res); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alen = int_array_len(a); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt n = os_realloc(*res, (reslen + alen + 1) * sizeof(int)); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (n == NULL) { 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(*res); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *res = NULL; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i <= alen; i++) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt n[reslen + i] = a[i]; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *res = n; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int freq_cmp(const void *a, const void *b) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int _a = *(int *) a; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int _b = *(int *) b; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_a == 0) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_b == 0) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return _a - _b; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void int_array_sort_unique(int *a) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int alen; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, j; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a == NULL) 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alen = int_array_len(a); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt qsort(a, alen, sizeof(int), freq_cmp); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i = 0; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt j = 1; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (a[i] && a[j]) { 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a[i] == a[j]) { 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt j++; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt a[++i] = a[j++]; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a[i]) 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt a[i] = 0; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_params *params) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 1); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = ieee80211_sta_req_scan(wpa_s, params); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_drv_scan(wpa_s, params); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 0); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_scan_done(wpa_s, 0); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->scan_runs++; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_driver_scan_filter * 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_filter *ssids; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t count; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *num_ssids = 0; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!conf->filter_ssids) 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) { 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->ssid && ssid->ssid_len) 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter)); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssids == NULL) 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ssid = conf->ssid; ssid; ssid = ssid->next) { 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->ssid || !ssid->ssid_len) 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssids[*num_ssids].ssid_len = ssid->ssid_len; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*num_ssids)++; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ssids; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int scan_req = 0, ret; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *wps_ie = NULL; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wps = 0; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_params params; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t max_ssids; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_states prev_state; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->disconnected && !wpa_s->scan_req) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_supplicant_enabled_networks(wpa_s->conf) && 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !wpa_s->scan_req) { 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ap_scan != 0 && 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) { 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - " 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "overriding ap_scan configuration"); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->conf->ap_scan = 0; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_ap_scan_changed(wpa_s); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ap_scan == 0) { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_gen_assoc_event(wpa_s); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) || 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->conf->ap_scan == 2) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_ssids = 1; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_ssids = wpa_s->max_scan_ssids; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (max_ssids > WPAS_MAX_SCAN_SSIDS) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_ssids = WPAS_MAX_SCAN_SSIDS; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps = wpas_wps_in_use(wpa_s->conf, &req_type); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt scan_req = wpa_s->scan_req; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->scan_req = 0; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev_state = wpa_s->wpa_state; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state == WPA_DISCONNECTED || 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->wpa_state == WPA_INACTIVE) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_SCANNING); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the starting point from which to continue scanning */ 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_s->conf->ssid; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) { 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == wpa_s->prev_scan_ssid) { 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (scan_req != 2 && (wpa_s->conf->ap_scan == 2 || 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->connect_without_scan)) { 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->connect_without_scan = 0; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_assoc_try(wpa_s, ssid); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_s->conf->ap_scan == 2) { 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * User-initiated scan request in ap_scan == 2; scan with 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wildcard SSID. 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = NULL; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *start = ssid, *tssid; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int freqs_set = 0; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL && max_ssids > 1) 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_s->conf->ssid; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->disabled && ssid->scan_ssid) { 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->ssid, ssid->ssid_len); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssids[params.num_ssids].ssid = 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->ssid; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssids[params.num_ssids].ssid_len = 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->ssid_len; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.num_ssids++; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.num_ssids + 1 >= max_ssids) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == start) 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL && max_ssids > 1 && 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start != wpa_s->conf->ssid) 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_s->conf->ssid; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tssid->disabled) 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((params.freqs || !freqs_set) && tssid->scan_freq) { 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int_array_concat(¶ms.freqs, 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tssid->scan_freq); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(params.freqs); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs = NULL; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freqs_set = 1; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int_array_sort_unique(params.freqs); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid) { 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = ssid; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (max_ssids > 1) { 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in " 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the scan request"); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.num_ssids++; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for specific " 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SSID(s)"); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.num_ssids++; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard " 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SSID"); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->wps->dev.p2p = 1; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wps) { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps = 1; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req_type = WPS_REQ_ENROLLEE_INFO; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.freqs == NULL && wpa_s->p2p_in_provisioning && 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->go_params) { 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Optimize provisioning state scan based on GO information */ 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->p2p_in_provisioning < 5 && 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->go_params->freq > 0) { 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO " 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "preferred frequency %d MHz", 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->go_params->freq); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs = os_zalloc(2 * sizeof(int)); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.freqs) 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs[0] = wpa_s->go_params->freq; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_s->p2p_in_provisioning < 8 && 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->go_params->freq_list[0]) { 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common " 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "channels"); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int_array_concat(¶ms.freqs, 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->go_params->freq_list); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.freqs) 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int_array_sort_unique(params.freqs); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->p2p_in_provisioning++; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) { 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Optimize post-provisioning scan based on channel used 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * during provisioning. 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz " 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "that was used during provisioning", wpa_s->wps_freq); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs = os_zalloc(2 * sizeof(int)); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.freqs) 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs[0] = wpa_s->wps_freq; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->after_wps--; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps) { 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev, 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->wps->uuid, req_type, 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NULL); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_ie) { 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.extra_ies = wpabuf_head(wps_ie); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.extra_ies_len = wpabuf_len(wps_ie); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_ie) { 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&wps_ie, 100) == 0) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_p2p_scan_ie(wpa_s, wps_ie); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.extra_ies = wpabuf_head(wps_ie); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.extra_ies_len = wpabuf_len(wps_ie); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.freqs == NULL && wpa_s->next_scan_freqs) { 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously " 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "generated frequency list"); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs = wpa_s->next_scan_freqs; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_s->next_scan_freqs); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->next_scan_freqs = NULL; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.filter_ssids = wpa_supplicant_build_filter_ssids( 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->conf, ¶ms.num_filter_ssids); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps_ie); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(params.freqs); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(params.filter_ssids); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan"); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev_state != wpa_s->wpa_state) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, prev_state); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, 1, 0); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_req_scan - Schedule a scan for neighboring access points 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sec: Number of seconds after which to scan 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @usec: Number of microseconds after which to scan 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to schedule a scan for neighboring access points after 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the specified time. 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* If there's at least one network that should be specifically scanned 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * then don't cancel the scan and reschedule. Some drivers do 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * background scanning which generates frequent scan results, and that 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * causes the specific SSID scan to get continually pushed back and 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * never happen, which causes hidden APs to never get probe-scanned. 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) && 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->conf->ap_scan == 1) { 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid = wpa_s->conf->ssid; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->disabled && ssid->scan_ssid) 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid) { 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Not rescheduling scan to " 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ensure that specific SSID scans occur"); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec, usec); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_cancel_scan - Cancel a scheduled scan request 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to cancel a scan request scheduled with 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_req_scan(). 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request"); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 53220df807cb700c516ff346732f1bc8f914d0d26d8Dmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 0); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int scanning) 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->scanning != scanning) { 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->scanning = scanning; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_scanning(wpa_s); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_get_max_rate(const struct wpa_scan_res *res) 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rate = 0; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; ie && i < ie[1]; i++) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie[i + 2] & 0x7f) > rate) 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate = ie[i + 2] & 0x7f; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; ie && i < ie[1]; i++) { 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie[i + 2] & 0x7f) > rate) 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate = ie[i + 2] & 0x7f; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return rate; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (res + 1); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + res->ie_len; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == ie) 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 vendor_type) 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (res + 1); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + res->ie_len; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_type == WPA_GET_BE32(&pos[2])) 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 vendor_type) 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(res->ie_len); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (res + 1); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + res->ie_len; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_type == WPA_GET_BE32(&pos[2])) 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(buf) == 0) { 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = NULL; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpa_scan_get_vendor_ie_multi_beacon( 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_scan_res *res, u32 vendor_type) 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res->beacon_ie_len == 0) 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(res->beacon_ie_len); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (res + 1); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res->ie_len; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + res->beacon_ie_len; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_type == WPA_GET_BE32(&pos[2])) 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(buf) == 0) { 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = NULL; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Compare function for sorting scan results. Return >0 if @b is considered 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * better. */ 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_result_compar(const void *a, const void *b) 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wa = (void *) a; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wb = (void *) b; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wa = *_wa; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wb = *_wb; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wpa_a, wpa_b, maxrate_a, maxrate_b; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA/WPA2 support preferred */ 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_b && !wpa_a) 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_b && wpa_a) 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* privacy support preferred */ 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wb->caps & IEEE80211_CAP_PRIVACY)) 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wa->caps & IEEE80211_CAP_PRIVACY) && 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wb->caps & IEEE80211_CAP_PRIVACY) == 0) 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* best/max rate preferred if signal level close enough XXX */ 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) || 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxrate_a = wpa_scan_get_max_rate(wa); 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxrate_b = wpa_scan_get_max_rate(wb); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (maxrate_a != maxrate_b) 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return maxrate_b - maxrate_a; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* use freq for channel preference */ 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* all things being equal, use signal level; if signal levels are 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identical, use quality values since some drivers may only report 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that value and leave the signal level zero */ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wb->level == wa->level) 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wb->qual - wa->qual; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wb->level - wa->level; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Compare function for sorting scan results when searching a WPS AP for 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * provisioning. Return >0 if @b is considered better. */ 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_result_wps_compar(const void *a, const void *b) 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wa = (void *) a; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wb = (void *) b; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wa = *_wa; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wb = *_wb; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int uses_wps_a, uses_wps_b; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *wps_a, *wps_b; 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Optimization - check WPS IE existence before allocated memory and 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * doing full reassembly. */ 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uses_wps_a && !uses_wps_b) 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!uses_wps_a && uses_wps_b) 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uses_wps_a && uses_wps_b) { 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE); 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_ap_priority_compar(wps_a, wps_b); 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps_a); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps_b); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Do not use current AP security policy as a sorting criteria during 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS provisioning step since the AP may get reconfigured at the 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * completion of provisioning. 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* all things being equal, use signal level; if signal levels are 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identical, use quality values since some drivers may only report 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that value and leave the signal level zero */ 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wb->level == wa->level) 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wb->qual - wa->qual; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wb->level - wa->level; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_get_scan_results - Get scan results 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @info: Information about what was scanned or %NULL if not available 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_scan: Whether a new scan was performed 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Scan results, %NULL on failure 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function request the current scan results from the driver and updates 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the local BSS list wpa_s->bss. The caller is responsible for freeing the 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * results with wpa_scan_results_free(). 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_scan_results * 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct scan_info *info, int new_scan) 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*compar)(const void *, const void *) = wpa_scan_result_compar; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt scan_res = ieee80211_sta_get_scan_results(wpa_s); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt scan_res = wpa_drv_get_scan_results2(wpa_s); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (scan_res == NULL) { 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results"); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpas_wps_in_progress(wpa_s)) { 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS " 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "provisioning rules"); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt compar = wpa_scan_result_wps_compar; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt compar); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bss_update_start(wpa_s); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < scan_res->num; i++) 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bss_update_scan_res(wpa_s, scan_res->res[i]); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bss_update_end(wpa_s, info, new_scan); 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return scan_res; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res; 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (scan_res == NULL) 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_results_free(scan_res); 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_scan_results_free(struct wpa_scan_results *res) 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == NULL) 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < res->num; i++) 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res->res[i]); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res->res); 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 842