18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Scanning 3fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 143a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt#include "common/wpa_ctrl.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_supplicant.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_supplicant.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h" 2104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "hs20_supplicant.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "notify.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bss.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "scan.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_supplicant_get_ssid(wpa_s); 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->current_ssid == NULL) { 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid = ssid; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->current_ssid != NULL) 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_network_changed(wpa_s); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_initiate_eapol(wpa_s); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured " 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "network - generating associated event"); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpas_wps_in_use(struct wpa_supplicant *wpa_s, 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_request_type *req_type) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wps = 0; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps = 1; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *req_type = wpas_wps_get_req_type(ssid); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->eap.phase1) 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(ssid->eap.phase1, "pbc=1")) 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 2; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P 70d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p && 71d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt !wpa_s->conf->p2p_disabled) { 72c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->wps->dev.p2p = 1; 73c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!wps) { 74c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wps = 1; 75c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt *req_type = WPS_REQ_ENROLLEE_INFO; 76c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */ 791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wps; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 85a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 86a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_enabled_networks - Check whether there are enabled networks 87a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 88a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 if no networks are enabled, >0 if networks are enabled 89a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * 90a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to figure out whether any networks (or Interworking 91a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * with enabled credentials and auto_interworking) are present in the current 92a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * configuration. 93a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 9404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_ssid *ssid = wpa_s->conf->ssid; 97aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt int count = 0, disabled = 0; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 9904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpas_network_disabled(wpa_s, ssid)) 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 101aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt else 102aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt disabled++; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->conf->cred && wpa_s->conf->interworking && 10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->conf->auto_interworking) 10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt count++; 108aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt if (count == 0 && disabled > 0) { 109aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled " 110aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt "networks)", disabled); 111aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt } 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return count; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 12004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpas_network_disabled(wpa_s, ssid)) 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ap_scan=2 mode - try to associate with each SSID. */ 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL) { 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached " 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "end of scan list - go back to beginning"); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->next) { 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Continue from the next SSID on the next attempt. */ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = ssid; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Start from the beginning of the SSID list. */ 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_associate(wpa_s, NULL, ssid); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 144fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 146fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_supplicant *wpa_s = work->wpa_s; 147fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_scan_params *params = work->ctx; 148fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int ret; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 150fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (deinit) { 151bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt if (!work->started) { 152bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt wpa_scan_free_params(params); 153bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt return; 154bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt } 155bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 0); 156bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt wpas_notify_scan_done(wpa_s, 0); 157bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt wpa_s->scan_work = NULL; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 161661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (wpas_update_random_addr_disassoc(wpa_s) < 0) { 162661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, 163661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt "Failed to assign random MAC address for a scan"); 164661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt radio_work_done(work); 165661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return; 166661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 167661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 168fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 1); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 170fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_s->clear_driver_scan_cache) 171fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->only_new_results = 1; 172fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = wpa_drv_scan(wpa_s, params); 173fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_scan_free_params(params); 174fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt work->ctx = NULL; 175fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ret) { 176fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 0); 177fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_notify_scan_done(wpa_s, 0); 178fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt radio_work_done(work); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 181fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 182fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&wpa_s->scan_trigger_time); 183fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->scan_runs++; 184fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->normal_scans++; 185fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->own_scan_requested = 1; 186fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->clear_driver_scan_cache = 0; 187fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->scan_work = work; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 191a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 192a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_trigger_scan - Request driver to start a scan 193a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 194a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @params: Scan parameters 195a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure 196a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_params *params) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 200fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_scan_params *ctx; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 202fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_s->scan_work) { 203fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending"); 204fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 205fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 207fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ctx = wpa_scan_clone_params(params); 208fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ctx == NULL) 209fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 210fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 211fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0) 212fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt { 213fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_scan_free_params(ctx); 214fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 217fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 2181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void 2221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtwpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx) 2231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 2251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan"); 2271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_supplicant_req_sched_scan(wpa_s)) 2291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void 2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtwpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx) 2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it"); 2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scan_timed_out = 1; 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_cancel_sched_scan(wpa_s); 2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 245e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtint wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s, 246e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt struct wpa_driver_scan_params *params, 247e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt int interval) 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 250b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 1); 2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000); 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret) 2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_notify_scanning(wpa_s, 0); 255b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt else 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scanning = 1; 2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 262e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtint wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s) 2631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 2651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = wpa_drv_stop_sched_scan(wpa_s); 2671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret) { 2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!"); 2691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* TODO: what to do if stopping fails? */ 2701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_driver_scan_filter * 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids) 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_filter *ssids; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t count; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *num_ssids = 0; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!conf->filter_ssids) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->ssid && ssid->ssid_len) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter)); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssids == NULL) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ssid = conf->ssid; ssid; ssid = ssid->next) { 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ssid->ssid || !ssid->ssid_len) 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssids[*num_ssids].ssid_len = ssid->ssid_len; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*num_ssids)++; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ssids; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpa_supplicant_optimize_freqs( 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params) 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->freqs == NULL && wpa_s->p2p_in_provisioning && 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->go_params) { 3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Optimize provisioning state scan based on GO information */ 3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->p2p_in_provisioning < 5 && 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->go_params->freq > 0) { 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO " 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "preferred frequency %d MHz", 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->go_params->freq); 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->freqs = os_zalloc(2 * sizeof(int)); 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->freqs) 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->freqs[0] = wpa_s->go_params->freq; 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (wpa_s->p2p_in_provisioning < 8 && 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->go_params->freq_list[0]) { 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common " 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "channels"); 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int_array_concat(¶ms->freqs, 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->go_params->freq_list); 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->freqs) 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int_array_sort_unique(params->freqs); 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->p2p_in_provisioning++; 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 33615907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt 33715907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (params->freqs == NULL && wpa_s->p2p_in_invitation) { 33815907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt /* 33915907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt * Optimize scan based on GO information during persistent 34015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt * group reinvocation 34115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt */ 3426dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt if (wpa_s->p2p_in_invitation < 5 && 34315907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_s->p2p_invite_go_freq > 0) { 34415907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation", 34515907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_s->p2p_invite_go_freq); 34615907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params->freqs = os_zalloc(2 * sizeof(int)); 34715907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (params->freqs) 34815907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params->freqs[0] = wpa_s->p2p_invite_go_freq; 34915907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } 35015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_s->p2p_in_invitation++; 35115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (wpa_s->p2p_in_invitation > 20) { 35215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt /* 35315907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt * This should not really happen since the variable is 35415907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt * cleared on group removal, but if it does happen, make 35515907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt * sure we do not get stuck in special invitation scan 35615907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt * mode. 35715907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt */ 35815907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation"); 35915907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_s->p2p_in_invitation = 0; 36015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } 36115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */ 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) { 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Optimize post-provisioning scan based on channel used 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * during provisioning. 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz " 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "that was used during provisioning", wpa_s->wps_freq); 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->freqs = os_zalloc(2 * sizeof(int)); 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->freqs) 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->freqs[0] = wpa_s->wps_freq; 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->after_wps--; 376fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else if (wpa_s->after_wps) 377fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->after_wps--; 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 379c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq) 380c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt { 381c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Optimize provisioning scan based on already known channel */ 382c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz", 383c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->wps_freq); 384c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt params->freqs = os_zalloc(2 * sizeof(int)); 385c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (params->freqs) 386c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt params->freqs[0] = wpa_s->wps_freq; 387c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->known_wps_freq = 0; /* only do this once */ 388c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */ 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s, 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf) 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->conf->interworking == 0) 3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB); 401f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 6); 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, 0x00); 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, 0x00); 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, 0x00); 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */ 406f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0x00); 407f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 408f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0x40); /* Bit 46 - WNM-Notification */ 409f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#else /* CONFIG_HS20 */ 410f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0x00); 411f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 4121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, WLAN_EID_INTERWORKING); 4141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 : 4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1 + ETH_ALEN); 4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, wpa_s->conf->access_network_type); 4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* No Venue Info */ 4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!is_zero_ether_addr(wpa_s->conf->hessid)) 4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN); 4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 42461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) 4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *extra_ie = NULL; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wps = 0; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->conf->interworking && 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_resize(&extra_ie, 100) == 0) 4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_add_interworking_elements(wpa_s, extra_ie); 4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wps = wpas_wps_in_use(wpa_s, &req_type); 4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wps) { 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *wps_ie; 44304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON : 44404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt DEV_PW_DEFAULT, 44504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt &wpa_s->wps->dev, 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->wps->uuid, req_type, 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0, NULL); 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wps_ie) { 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0) 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_buf(extra_ie, wps_ie); 4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(wps_ie); 4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P 4561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wps) { 4571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); 4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_resize(&extra_ie, ielen) == 0) 4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_p2p_scan_ie(wpa_s, extra_ie); 4601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */ 4621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */ 4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 46551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#ifdef CONFIG_HS20 46651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0) 467f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpas_hs20_add_indication(extra_ie, -1); 46851b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#endif /* CONFIG_HS20 */ 46951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 4701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return extra_ie; 4711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 474d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_P2P 475d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 476d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt/* 477d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * Check whether there are any enabled networks or credentials that could be 478d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * used for a non-P2P connection. 479d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */ 480d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int non_p2p_network_enabled(struct wpa_supplicant *wpa_s) 481d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 482d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_ssid *ssid; 483d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 484d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 485d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpas_network_disabled(wpa_s, ssid)) 486d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt continue; 487d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (!ssid->p2p_group) 488d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 1; 489d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 490d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 491d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_s->conf->cred && wpa_s->conf->interworking && 492d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->conf->auto_interworking) 493d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 1; 494d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 495d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 496d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 497d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 498ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt#endif /* CONFIG_P2P */ 499d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 500d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 501b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, 502b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt u16 num_modes, 503b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt enum hostapd_hw_mode mode) 504b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{ 505b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt u16 i; 506b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 507b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt for (i = 0; i < num_modes; i++) { 508b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt if (modes[i].mode == mode) 509b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt return &modes[i]; 510b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt } 511b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 512b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt return NULL; 513b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt} 514b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 515b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 516b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s, 517b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt enum hostapd_hw_mode band, 518b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt struct wpa_driver_scan_params *params) 519b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{ 520b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt /* Include only supported channels for the specified band */ 521b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt struct hostapd_hw_modes *mode; 522b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt int count, i; 523b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 524b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band); 525b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt if (mode == NULL) { 526b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt /* No channels supported in this band - use empty list */ 527b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt params->freqs = os_zalloc(sizeof(int)); 528b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt return; 529b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt } 530b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 531b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int)); 532b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt if (params->freqs == NULL) 533b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt return; 534b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt for (count = 0, i = 0; i < mode->num_channels; i++) { 535b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) 536b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt continue; 537b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt params->freqs[count++] = mode->channels[i].freq; 538b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt } 539b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt} 540b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 541b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 542b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidtstatic void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, 543b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt struct wpa_driver_scan_params *params) 544b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt{ 545b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt if (wpa_s->hw.modes == NULL) 546b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt return; /* unknown what channels the driver supports */ 547b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt if (params->freqs) 548b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt return; /* already using a limited channel set */ 549b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt if (wpa_s->setband == WPA_SETBAND_5G) 550b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, 551b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt params); 552b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt else if (wpa_s->setband == WPA_SETBAND_2G) 553b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, 554b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt params); 555b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt} 556b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 557b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 558c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidtstatic void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s, 559c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt struct wpa_driver_scan_params *params, 560c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t max_ssids) 561c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt{ 562c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt unsigned int i; 563c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt struct wpa_ssid *ssid; 564c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 565c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt for (i = 0; i < wpa_s->scan_id_count; i++) { 566c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt unsigned int j; 567c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 568c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]); 569c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (!ssid || !ssid->scan_ssid) 570c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt continue; 571c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 572c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt for (j = 0; j < params->num_ssids; j++) { 573c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (params->ssids[j].ssid_len == ssid->ssid_len && 574c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt params->ssids[j].ssid && 575c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp(params->ssids[j].ssid, ssid->ssid, 576c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt ssid->ssid_len) == 0) 577c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt break; 578c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt } 579c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (j < params->num_ssids) 580c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt continue; /* already in the list */ 581c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 582c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (params->num_ssids + 1 > max_ssids) { 583c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_printf(MSG_DEBUG, 584c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt "Over max scan SSIDs for manual request"); 585c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt break; 586c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt } 587c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 588c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s", 589c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 590c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt params->ssids[params->num_ssids].ssid = ssid->ssid; 591c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt params->ssids[params->num_ssids].ssid_len = ssid->ssid_len; 592c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt params->num_ssids++; 593c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt } 594c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 595c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_s->scan_id_count = 0; 596c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt} 597c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 598c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) 6001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 6011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 6021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ssid *ssid; 603d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int ret; 60404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *extra_ie = NULL; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_params params; 60604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_scan_params *scan_params; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t max_ssids; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_states prev_state; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6101846323989242844f0e857458a8939fa5836429cDmitry Shmidt if (wpa_s->pno || wpa_s->pno_sched_pending) { 6111846323989242844f0e857458a8939fa5836429cDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress"); 6121846323989242844f0e857458a8939fa5836429cDmitry Shmidt return; 6131846323989242844f0e857458a8939fa5836429cDmitry Shmidt } 6141846323989242844f0e857458a8939fa5836429cDmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 620d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) { 621aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan"); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 625e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 6265887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt if (wpa_s->scanning) { 627e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt /* 628e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt * If we are already in scanning state, we shall reschedule the 629e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt * the incoming scan request. 630e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt */ 631e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req"); 632e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 1, 0); 6335887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt return; 6345887a9d552f3d9d612011daba073e076daab5b2aDmitry Shmidt } 635e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 63604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpa_supplicant_enabled_networks(wpa_s) && 637d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->scan_req == NORMAL_SCAN_REQ) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ap_scan != 0 && 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) { 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - " 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "overriding ap_scan configuration"); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->conf->ap_scan = 0; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_ap_scan_changed(wpa_s); 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->conf->ap_scan == 0) { 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_gen_assoc_event(wpa_s); 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 656fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpas_p2p_in_progress(wpa_s)) { 657fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress"); 658fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, 5, 0); 659051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return; 660051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 661051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 6621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->conf->ap_scan == 2) 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_ssids = 1; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_ssids = wpa_s->max_scan_ssids; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (max_ssids > WPAS_MAX_SCAN_SSIDS) 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_ssids = WPAS_MAX_SCAN_SSIDS; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 67001904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt wpa_s->last_scan_req = wpa_s->scan_req; 671d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->scan_req = NORMAL_SCAN_REQ; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev_state = wpa_s->wpa_state; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state == WPA_DISCONNECTED || 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->wpa_state == WPA_INACTIVE) 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_SCANNING); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 68004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 68104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * If autoscan has set its own scanning parameters 68204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 68304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->autoscan_params != NULL) { 68404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt scan_params = wpa_s->autoscan_params; 68504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto scan; 68604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 68704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 68801904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt if (wpa_s->last_scan_req != MANUAL_SCAN_REQ && 68901904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt wpa_s->connect_without_scan) { 69075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 69175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (ssid == wpa_s->connect_without_scan) 69275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen break; 69375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 69475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_s->connect_without_scan = NULL; 69575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (ssid) { 69675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "Start a pre-selected network " 69775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen "without scan step"); 69875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_supplicant_associate(wpa_s, NULL, ssid); 69975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return; 70075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 70175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 70275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 70304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_P2P 70404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) && 70504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->go_params) { 706cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)", 707cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_s->p2p_in_provisioning, 708cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_s->show_group_started); 70904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params.ssids[0].ssid = wpa_s->go_params->ssid; 71004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params.ssids[0].ssid_len = wpa_s->go_params->ssid_len; 71104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params.num_ssids = 1; 71204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto ssid_list_set; 71304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 71415907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt 71515907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (wpa_s->p2p_in_invitation) { 71615907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (wpa_s->current_ssid) { 71715907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation"); 71815907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params.ssids[0].ssid = wpa_s->current_ssid->ssid; 71915907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params.ssids[0].ssid_len = 72015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_s->current_ssid->ssid_len; 72115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params.num_ssids = 1; 72215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } else { 72315907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation"); 72415907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } 72515907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt goto ssid_list_set; 72615907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } 72704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_P2P */ 72804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the starting point from which to continue scanning */ 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_s->conf->ssid; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) { 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == wpa_s->prev_scan_ssid) { 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 74101904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt if (wpa_s->last_scan_req != MANUAL_SCAN_REQ && 74201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt wpa_s->conf->ap_scan == 2) { 74375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_s->connect_without_scan = NULL; 744c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->prev_scan_wildcard = 0; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_assoc_try(wpa_s, ssid); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_s->conf->ap_scan == 2) { 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * User-initiated scan request in ap_scan == 2; scan with 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wildcard SSID. 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = NULL; 7539866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) { 7549866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt /* 7559866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * Perform single-channel single-SSID scan for 7569866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * reassociate-to-same-BSS operation. 7579866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt */ 7589866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt /* Setup SSID */ 7599866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ssid = wpa_s->current_ssid; 7609866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", 7619866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ssid->ssid, ssid->ssid_len); 7629866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.ssids[0].ssid = ssid->ssid; 7639866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.ssids[0].ssid_len = ssid->ssid_len; 7649866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.num_ssids = 1; 7659866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 7669866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt /* 7679866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * Allocate memory for frequency array, allocate one extra 7689866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * slot for the zero-terminator. 7699866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt */ 7709866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.freqs = os_malloc(sizeof(int) * 2); 7719866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (params.freqs == NULL) { 7729866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed"); 7739866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return; 7749866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 7759866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.freqs[0] = wpa_s->assoc_freq; 7769866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.freqs[1] = 0; 7779866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 7789866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt /* 7799866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * Reset the reattach flag so that we fall back to full scan if 7809866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * this scan fails. 7819866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt */ 7829866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_s->reattach = 0; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *start = ssid, *tssid; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int freqs_set = 0; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL && max_ssids > 1) 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_s->conf->ssid; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ssid) { 78904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpas_network_disabled(wpa_s, ssid) && 79004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->scan_ssid) { 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->ssid, ssid->ssid_len); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssids[params.num_ssids].ssid = 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->ssid; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssids[params.num_ssids].ssid_len = 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->ssid_len; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.num_ssids++; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.num_ssids + 1 >= max_ssids) 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = ssid->next; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == start) 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL && max_ssids > 1 && 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start != wpa_s->conf->ssid) 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_s->conf->ssid; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 809c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_s->scan_id_count && 810c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_s->last_scan_req == MANUAL_SCAN_REQ) 811c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_set_scan_ssids(wpa_s, ¶ms, max_ssids); 812c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { 81404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpas_network_disabled(wpa_s, tssid)) 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((params.freqs || !freqs_set) && tssid->scan_freq) { 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int_array_concat(¶ms.freqs, 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tssid->scan_freq); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(params.freqs); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs = NULL; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freqs_set = 1; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int_array_sort_unique(params.freqs); 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (ssid && max_ssids == 1) { 829c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 830c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * If the driver is limited to 1 SSID at a time interleave 831c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * wildcard SSID scans with specific SSID scans to avoid 832c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * waiting a long time for a wildcard scan. 833c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 834c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!wpa_s->prev_scan_wildcard) { 835c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt params.ssids[0].ssid = NULL; 836c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt params.ssids[0].ssid_len = 0; 837c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->prev_scan_wildcard = 1; 838c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for " 839c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "wildcard SSID (Interleave with specific)"); 840c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 841c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->prev_scan_ssid = ssid; 842c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->prev_scan_wildcard = 0; 843c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, 844c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "Starting AP scan for specific SSID: %s", 845c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 847c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else if (ssid) { 848c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* max_ssids > 1 */ 849c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 850c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_s->prev_scan_ssid = ssid; 851c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in " 852c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "the scan request"); 853c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt params.num_ssids++; 854fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && 855fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_passive && params.num_ssids == 0) { 856fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request"); 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.num_ssids++; 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard " 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SSID"); 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 86304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_P2P 86404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtssid_list_set: 86504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_P2P */ 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_optimize_freqs(wpa_s, ¶ms); 86861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt extra_ie = wpa_supplicant_extra_ies(wpa_s); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 870fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && 871fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_only_new) 872fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params.only_new_results = 1; 873fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 874fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL && 875fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_freqs) { 876fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels"); 877fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params.freqs = wpa_s->manual_scan_freqs; 878fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_freqs = NULL; 879fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 880fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.freqs == NULL && wpa_s->next_scan_freqs) { 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously " 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "generated frequency list"); 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freqs = wpa_s->next_scan_freqs; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_s->next_scan_freqs); 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->next_scan_freqs = NULL; 888b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt wpa_setband_scan_freqs(wpa_s, ¶ms); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 89051b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt /* See if user specified frequencies. If so, scan only those. */ 89151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (wpa_s->conf->freq_list && !params.freqs) { 89251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, 89351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt "Optimize scan based on conf->freq_list"); 89451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); 89551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt } 89651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 897ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt /* Use current associated channel? */ 898ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt if (wpa_s->conf->scan_cur_freq && !params.freqs) { 899c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt unsigned int num = wpa_s->num_multichan_concurrent; 900c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 901c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt params.freqs = os_calloc(num + 1, sizeof(int)); 902c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (params.freqs) { 903c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt num = get_shared_radio_freqs(wpa_s, params.freqs, num); 904c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (num > 0) { 905c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the " 906c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "current operating channels since " 907c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "scan_cur_freq is enabled"); 908c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } else { 909c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_free(params.freqs); 910c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt params.freqs = NULL; 911c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 912ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt } 913ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt } 914ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.filter_ssids = wpa_supplicant_build_filter_ssids( 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->conf, ¶ms.num_filter_ssids); 9171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (extra_ie) { 9181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.extra_ies = wpabuf_head(extra_ie); 9191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.extra_ies_len = wpabuf_len(extra_ie); 9201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P 923413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt if (wpa_s->p2p_in_provisioning || wpa_s->p2p_in_invitation || 92404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (wpa_s->show_group_started && wpa_s->go_params)) { 9251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 9261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * The interface may not yet be in P2P mode, so we have to 9271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * explicitly request P2P probe to disable CCK rates. 9281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 9291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.p2p_probe = 1; 9301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_P2P */ 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 93304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt scan_params = ¶ms; 93404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 93504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtscan: 936d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_P2P 937d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* 938d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * If the driver does not support multi-channel concurrency and a 939d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * virtual interface that shares the same radio with the wpa_s interface 940d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * is operating there may not be need to scan other channels apart from 941d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * the current operating channel on the other virtual interface. Filter 942d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * out other channels in case we are trying to find a connection for a 943d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * station interface when we are not configured to prefer station 944d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * connection and a concurrent operation is already in process. 945d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */ 94601904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt if (wpa_s->scan_for_connection && 94701904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt wpa_s->last_scan_req == NORMAL_SCAN_REQ && 948d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt !scan_params->freqs && !params.freqs && 949d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpas_is_p2p_prioritized(wpa_s) && 950d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE && 951d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt non_p2p_network_enabled(wpa_s)) { 952c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt unsigned int num = wpa_s->num_multichan_concurrent; 953c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 954c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt params.freqs = os_calloc(num + 1, sizeof(int)); 955c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (params.freqs) { 956c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt num = get_shared_radio_freqs(wpa_s, params.freqs, num); 957c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (num > 0 && num == wpa_s->num_multichan_concurrent) { 958c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used"); 959c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } else { 960c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_free(params.freqs); 961c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt params.freqs = NULL; 962c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 963d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 964d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 965d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_P2P */ 966d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 96704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ret = wpa_supplicant_trigger_scan(wpa_s, scan_params); 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 969fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs && 970fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !wpa_s->manual_scan_freqs) { 971fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt /* Restore manual_scan_freqs for the next attempt */ 972fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_freqs = params.freqs; 973fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params.freqs = NULL; 974fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 975fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 9761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(extra_ie); 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(params.freqs); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(params.filter_ssids); 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan"); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev_state != wpa_s->wpa_state) 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, prev_state); 984d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* Restore scan_req since we will try to scan again */ 98501904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt wpa_s->scan_req = wpa_s->last_scan_req; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, 1, 0); 987d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } else { 988d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->scan_for_connection = 0; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9934b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtvoid wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec) 9944b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 995fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime remaining, new_int; 9964b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt int cancelled; 9974b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 9984b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL, 9994b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt &remaining); 10004b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 10014b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt new_int.sec = sec; 10024b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt new_int.usec = 0; 1003fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (cancelled && os_reltime_before(&remaining, &new_int)) { 10044b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt new_int.sec = remaining.sec; 10054b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt new_int.usec = remaining.usec; 10064b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt } 10074b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1008051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cancelled) { 1009051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt eloop_register_timeout(new_int.sec, new_int.usec, 1010051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_supplicant_scan, wpa_s, NULL); 1011051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 10124b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt wpa_s->scan_interval = sec; 10134b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 10144b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 10154b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_req_scan - Schedule a scan for neighboring access points 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sec: Number of seconds after which to scan 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @usec: Number of microseconds after which to scan 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to schedule a scan for neighboring access points after 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the specified time. 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1027fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s, 1028fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt NULL); 1029fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (res == 1) { 1030fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d.%06d sec", 1031e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt sec, usec); 1032fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else if (res == 0) { 1033fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner", 1034fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sec, usec); 1035fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else { 1036fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d.%06d sec", 1037fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sec, usec); 1038fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan 10451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 10461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @sec: Number of seconds after which to scan 10471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @usec: Number of microseconds after which to scan 1048a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success or -1 otherwise 10491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 10501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to schedule periodic scans for neighboring 10511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * access points after the specified time. 10521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 10531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s, 10541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int sec, int usec) 10551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 10561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!wpa_s->sched_scan_supported) 10571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 10581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eloop_register_timeout(sec, usec, 10601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_delayed_sched_scan_timeout, 10611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s, NULL); 10621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 10641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 10651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 10681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan 10691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 1070a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 is sched_scan was started or -1 otherwise 10711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 10721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to schedule periodic scans for neighboring 10731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * access points repeating the scan continuously. 10741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 10751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) 10761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 10771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_scan_params params; 107804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_scan_params *scan_params; 10791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum wpa_states prev_state; 108004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_ssid *ssid = NULL; 108161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *extra_ie = NULL; 10821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 10831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt unsigned int max_sched_scan_ssids; 10841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int wildcard = 0; 10851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int need_ssids; 10861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!wpa_s->sched_scan_supported) 10881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 10891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS) 10911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS; 10921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 10931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt max_sched_scan_ssids = wpa_s->max_sched_scan_ssids; 109404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload) 10951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 10961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->sched_scanning) { 10981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning"); 10991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 11001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt need_ssids = 0; 11031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 110404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) { 11051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Use wildcard SSID to find this network */ 11061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wildcard = 1; 110704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (!wpas_network_disabled(wpa_s, ssid) && 110804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->ssid_len) 11091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt need_ssids++; 111004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 111104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS 111204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpas_network_disabled(wpa_s, ssid) && 111304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->key_mgmt == WPA_KEY_MGMT_WPS) { 111404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 111504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Normal scan is more reliable and faster for WPS 111604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * operations and since these are for short periods of 111704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * time, the benefit of trying to use sched_scan would 111804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * be limited. 111904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 112004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of " 112104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "sched_scan for WPS"); 112204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 112304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 112404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS */ 11251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wildcard) 11271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt need_ssids++; 11281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->normal_scans < 3 && 11301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (need_ssids <= wpa_s->max_scan_ssids || 11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) { 11321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 11331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * When normal scan can speed up operations, use that for the 11341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * first operations before starting the sched_scan to allow 11351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * user space sleep more. We do this only if the normal scan 11361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * has functionality that is suitable for this or if the 11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * sched_scan does not have better support for multiple SSIDs. 11381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of " 11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "sched_scan for initial scans (normal_scans=%d)", 11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->normal_scans); 11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 11431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 11461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* If we can't allocate space for the filters, we just don't filter */ 11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.filter_ssids = os_zalloc(wpa_s->max_match_sets * 11491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sizeof(struct wpa_driver_scan_filter)); 11501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prev_state = wpa_s->wpa_state; 11521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->wpa_state == WPA_DISCONNECTED || 11531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->wpa_state == WPA_INACTIVE) 11541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_SCANNING); 11551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 115604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->autoscan_params != NULL) { 115704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt scan_params = wpa_s->autoscan_params; 115804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto scan; 115904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 116004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 11611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Find the starting point from which to continue scanning */ 11621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_s->conf->ssid; 11631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->prev_sched_ssid) { 11641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (ssid) { 11651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid == wpa_s->prev_sched_ssid) { 11661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = ssid->next; 11671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 11681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = ssid->next; 11701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!ssid || !wpa_s->prev_sched_ssid) { 11741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list"); 117551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (wpa_s->conf->sched_scan_interval) 117651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_s->sched_scan_interval = 117751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_s->conf->sched_scan_interval; 117804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->sched_scan_interval == 0) 117904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sched_scan_interval = 10; 11801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2; 11811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->first_sched_scan = 1; 11821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_s->conf->ssid; 11831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->prev_sched_ssid = ssid; 11841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wildcard) { 11871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan"); 11881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.num_ssids++; 11891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (ssid) { 119204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpas_network_disabled(wpa_s, ssid)) 11931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto next; 11941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params.num_filter_ssids < wpa_s->max_match_sets && 11961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.filter_ssids && ssid->ssid && ssid->ssid_len) { 11971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s", 11981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 11991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid, 12001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid, ssid->ssid_len); 12011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.filter_ssids[params.num_filter_ssids].ssid_len = 12021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid_len; 12031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.num_filter_ssids++; 12041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len) 12051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt { 12061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID " 12071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "filter for sched_scan - drop filter"); 12081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(params.filter_ssids); 12091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.filter_ssids = NULL; 12101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.num_filter_ssids = 0; 12111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) { 12141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params.num_ssids == max_sched_scan_ssids) 12151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; /* only room for broadcast SSID */ 12161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, 12171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "add to active scan ssid: %s", 12181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 12191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.ssids[params.num_ssids].ssid = 12201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid; 12211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.ssids[params.num_ssids].ssid_len = 12221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid_len; 12231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.num_ssids++; 12241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params.num_ssids >= max_sched_scan_ssids) { 12251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->prev_sched_ssid = ssid; 122604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt do { 122704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid = ssid->next; 122804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } while (ssid && 122904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (wpas_network_disabled(wpa_s, ssid) || 123004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt !ssid->scan_ssid)); 12311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 12321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt next: 12361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->prev_sched_ssid = ssid; 12371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = ssid->next; 12381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params.num_filter_ssids == 0) { 12411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(params.filter_ssids); 12421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.filter_ssids = NULL; 12431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 124561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt extra_ie = wpa_supplicant_extra_ies(wpa_s); 124661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (extra_ie) { 124761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params.extra_ies = wpabuf_head(extra_ie); 124861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params.extra_ies_len = wpabuf_len(extra_ie); 124961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 12501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12511846323989242844f0e857458a8939fa5836429cDmitry Shmidt if (wpa_s->conf->filter_rssi) 12521846323989242844f0e857458a8939fa5836429cDmitry Shmidt params.filter_rssi = wpa_s->conf->filter_rssi; 12531846323989242844f0e857458a8939fa5836429cDmitry Shmidt 1254661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt /* See if user specified frequencies. If so, scan only those. */ 1255661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (wpa_s->conf->freq_list && !params.freqs) { 1256661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, 1257661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt "Optimize scan based on conf->freq_list"); 1258661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); 1259661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 1260661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 126104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt scan_params = ¶ms; 126204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 126304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtscan: 12641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid || !wpa_s->first_sched_scan) { 12651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, 12661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Starting sched scan: interval %d timeout %d", 12671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout); 126804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 126904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, 127004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "Starting sched scan: interval %d (no timeout)", 127104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sched_scan_interval); 12721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1274b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt wpa_setband_scan_freqs(wpa_s, scan_params); 1275b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt 127604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params, 12771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scan_interval); 127861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(extra_ie); 12791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(params.filter_ssids); 12801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret) { 12811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan"); 12821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prev_state != wpa_s->wpa_state) 12831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_set_state(wpa_s, prev_state); 12841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 12851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* If we have more SSIDs to scan, add a timeout so we scan them too */ 12881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid || !wpa_s->first_sched_scan) { 12891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scan_timed_out = 0; 12901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eloop_register_timeout(wpa_s->sched_scan_timeout, 0, 12911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_sched_scan_timeout, 12921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s, NULL); 12931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->first_sched_scan = 0; 12941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scan_timeout /= 2; 12951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sched_scan_interval *= 2; 12962f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) { 12972f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt wpa_s->sched_scan_interval = 10; 12982f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2; 12992f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt } 13001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13022f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt /* If there is no more ssids, start next time from the beginning */ 13032f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt if (!ssid) 13042f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt wpa_s->prev_sched_ssid = NULL; 13052f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 13061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 13071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 13081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_cancel_scan - Cancel a scheduled scan request 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to cancel a scan request scheduled with 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_req_scan(). 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request"); 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 1325c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan 1326c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 1327c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * 1328c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * This function is used to stop a delayed scheduled scan. 1329c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt */ 1330c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtvoid wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s) 1331c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{ 1332c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (!wpa_s->sched_scan_supported) 1333c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return; 1334c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 1335c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan"); 1336c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout, 1337c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_s, NULL); 1338c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt} 1339c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 1340c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 1341c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt/** 13421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans 13431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 13441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 13451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to stop a periodic scheduled scan. 13461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 13471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s) 13481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 13491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!wpa_s->sched_scanning) 13501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 13511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan"); 13531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL); 13541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_stop_sched_scan(wpa_s); 13551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 13561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1358a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 1359a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_notify_scanning - Indicate possible scan state change 1360a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 1361a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @scanning: Whether scanning is currently in progress 1362a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * 1363a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is to generate scanning notifycations. It is called whenever 1364a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * there may have been a change in scanning (scan started, completed, stopped). 1365a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpas_notify_scanning() is called whenever the scanning state changed from the 1366a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * previously notified state. 1367a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int scanning) 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->scanning != scanning) { 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->scanning = scanning; 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_scanning(wpa_s); 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_get_max_rate(const struct wpa_scan_res *res) 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rate = 0; 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie; 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; ie && i < ie[1]; i++) { 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie[i + 2] & 0x7f) > rate) 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate = ie[i + 2] & 0x7f; 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; ie && i < ie[1]; i++) { 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie[i + 2] & 0x7f) > rate) 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate = ie[i + 2] & 0x7f; 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return rate; 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1400a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 1401a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_scan_get_ie - Fetch a specified information element from a scan result 1402a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @res: Scan result entry 1403a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @ie: Information element identitifier (WLAN_EID_*) 1404a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found 1405a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * 1406a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function returns the first matching information element in the scan 1407a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * result. 1408a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (res + 1); 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + res->ie_len; 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == ie) 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 1429a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_scan_get_vendor_ie - Fetch vendor information element from a scan result 1430a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @res: Scan result entry 1431a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @vendor_type: Vendor type (four octets starting the IE payload) 1432a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found 1433a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * 1434a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function returns the first matching information element in the scan 1435a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * result. 1436a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 vendor_type) 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (res + 1); 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + res->ie_len; 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_type == WPA_GET_BE32(&pos[2])) 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 14599657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result 14609657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * @res: Scan result entry 14619657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * @vendor_type: Vendor type (four octets starting the IE payload) 14629657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * Returns: Pointer to the information element (id field) or %NULL if not found 14639657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * 14649657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * This function returns the first matching information element in the scan 14659657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * result. 14669657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * 14679657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only 14689657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt * from Beacon frames instead of either Beacon or Probe Response frames. 14699657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt */ 14709657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidtconst u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, 14719657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt u32 vendor_type) 14729657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt{ 14739657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt const u8 *end, *pos; 14749657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt 14759657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt if (res->beacon_ie_len == 0) 14769657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt return NULL; 14779657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt 14789657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt pos = (const u8 *) (res + 1); 14799657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt pos += res->ie_len; 14809657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt end = pos + res->beacon_ie_len; 14819657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt 14829657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt while (pos + 1 < end) { 14839657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt if (pos + 2 + pos[1] > end) 14849657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt break; 14859657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 14869657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt vendor_type == WPA_GET_BE32(&pos[2])) 14879657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt return pos; 14889657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt pos += 2 + pos[1]; 14899657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt } 14909657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt 14919657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt return NULL; 14929657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt} 14939657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt 14949657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt 14959657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt/** 1496a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result 1497a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @res: Scan result entry 1498a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @vendor_type: Vendor type (four octets starting the IE payload) 1499a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: Pointer to the information element payload or %NULL if not found 1500a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * 1501a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function returns concatenated payload of possibly fragmented vendor 1502a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * specific information elements in the scan result. The caller is responsible 1503a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * for freeing the returned buffer. 1504a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 vendor_type) 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc(res->ie_len); 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (res + 1); 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + res->ie_len; 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_type == WPA_GET_BE32(&pos[2])) 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(buf) == 0) { 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = NULL; 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* 15371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Channels with a great SNR can operate at full rate. What is a great SNR? 15381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general 15391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * rule of thumb is that any SNR above 20 is good." This one 15401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23 15411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a 15421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * conservative value. 15431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 15441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define GREAT_SNR 30 15451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Compare function for sorting scan results. Return >0 if @b is considered 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * better. */ 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_result_compar(const void *a, const void *b) 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define IS_5GHZ(n) (n > 4000) 15511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define MIN(a,b) a < b ? a : b 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wa = (void *) a; 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wb = (void *) b; 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wa = *_wa; 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wb = *_wb; 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wpa_a, wpa_b, maxrate_a, maxrate_b; 15571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int snr_a, snr_b; 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA/WPA2 support preferred */ 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_b && !wpa_a) 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_b && wpa_a) 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* privacy support preferred */ 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wb->caps & IEEE80211_CAP_PRIVACY)) 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wa->caps & IEEE80211_CAP_PRIVACY) && 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wb->caps & IEEE80211_CAP_PRIVACY) == 0) 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) && 15791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !((wa->flags | wb->flags) & WPA_SCAN_NOISE_INVALID)) { 15801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt snr_a = MIN(wa->level - wa->noise, GREAT_SNR); 15811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt snr_b = MIN(wb->level - wb->noise, GREAT_SNR); 15821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 15831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Not suitable information to calculate SNR, so use level */ 15841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt snr_a = wa->level; 15851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt snr_b = wb->level; 15861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 15871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* best/max rate preferred if SNR close enough */ 15891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) || 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxrate_a = wpa_scan_get_max_rate(wa); 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxrate_b = wpa_scan_get_max_rate(wb); 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (maxrate_a != maxrate_b) 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return maxrate_b - maxrate_a; 15951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq)) 15961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return IS_5GHZ(wa->freq) ? -1 : 1; 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* use freq for channel preference */ 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* all things being equal, use SNR; if SNRs are 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identical, use quality values since some drivers may only report 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that value and leave the signal level zero */ 16041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (snr_b == snr_a) 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wb->qual - wa->qual; 16061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return snr_b - snr_a; 16071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#undef MIN 16081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#undef IS_5GHZ 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Compare function for sorting scan results when searching a WPS AP for 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * provisioning. Return >0 if @b is considered better. */ 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_scan_result_wps_compar(const void *a, const void *b) 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wa = (void *) a; 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **_wb = (void *) b; 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wa = *_wa; 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *wb = *_wb; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int uses_wps_a, uses_wps_b; 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *wps_a, *wps_b; 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Optimization - check WPS IE existence before allocated memory and 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * doing full reassembly. */ 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL; 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL; 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uses_wps_a && !uses_wps_b) 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!uses_wps_a && uses_wps_b) 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (uses_wps_a && uses_wps_b) { 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE); 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE); 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_ap_priority_compar(wps_a, wps_b); 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps_a); 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps_b); 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Do not use current AP security policy as a sorting criteria during 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS provisioning step since the AP may get reconfigured at the 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * completion of provisioning. 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* all things being equal, use signal level; if signal levels are 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identical, use quality values since some drivers may only report 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that value and leave the signal level zero */ 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wb->level == wa->level) 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wb->qual - wa->qual; 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wb->level - wa->level; 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void dump_scan_res(struct wpa_scan_results *scan_res) 16611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 16621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 16631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t i; 16641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (scan_res->res == NULL || scan_res->num == 0) 16661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 16671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_EXCESSIVE, "Sorted scan results"); 16691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < scan_res->num; i++) { 16711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_scan_res *r = scan_res->res[i]; 167204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *pos; 16731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((r->flags & (WPA_SCAN_LEVEL_DBM | WPA_SCAN_NOISE_INVALID)) 16741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt == WPA_SCAN_LEVEL_DBM) { 16751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int snr = r->level - r->noise; 16761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d " 1677f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "noise=%d level=%d snr=%d%s flags=0x%x " 1678f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "age=%u", 16791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(r->bssid), r->freq, r->qual, 16801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->noise, r->level, snr, 1681f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt snr >= GREAT_SNR ? "*" : "", r->flags, 1682f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt r->age); 16831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 16841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d " 1685f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "noise=%d level=%d flags=0x%x age=%u", 16861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(r->bssid), r->freq, r->qual, 1687f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt r->noise, r->level, r->flags, r->age); 16881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 168904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = (u8 *) (r + 1); 169004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (r->ie_len) 169104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len); 169204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += r->ie_len; 169304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (r->beacon_ie_len) 169404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs", 169504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos, r->beacon_ie_len); 16961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 16981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 16991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1701a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 1702a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_filter_bssid_match - Is the specified BSSID allowed 1703a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 1704a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @bssid: BSSID to check 1705a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 if the BSSID is filtered or 1 if not 1706a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * 1707a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to filter out specific BSSIDs from scan reslts mainly 1708a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * for testing purposes (SET bssid_filter ctrl_iface command). 1709a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 171004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s, 171104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *bssid) 171204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 171304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t i; 171404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 171504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->bssid_filter == NULL) 171604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 171704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 171804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < wpa_s->bssid_filter_count; i++) { 171904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid, 172004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ETH_ALEN) == 0) 172104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 172204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 172304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 172404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 172504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 172604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 172704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 172804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void filter_scan_res(struct wpa_supplicant *wpa_s, 172904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_scan_results *res) 173004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 173104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t i, j; 173204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 173304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->bssid_filter == NULL) 173404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 173504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 173604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0, j = 0; i < res->num; i++) { 173704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_supplicant_filter_bssid_match(wpa_s, 173804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res->res[i]->bssid)) { 173904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res->res[j++] = res->res[i]; 174004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 174104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(res->res[i]); 174204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res->res[i] = NULL; 174304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 174404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 174504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 174604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (res->num != j) { 174704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Filtered out %d scan results", 174804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (int) (res->num - j)); 174904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res->num = j; 175004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 175104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 175204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 175304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_get_scan_results - Get scan results 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @info: Information about what was scanned or %NULL if not available 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @new_scan: Whether a new scan was performed 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Scan results, %NULL on failure 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function request the current scan results from the driver and updates 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the local BSS list wpa_s->bss. The caller is responsible for freeing the 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * results with wpa_scan_results_free(). 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_scan_results * 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct scan_info *info, int new_scan) 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res; 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*compar)(const void *, const void *) = wpa_scan_result_compar; 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt scan_res = wpa_drv_get_scan_results2(wpa_s); 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (scan_res == NULL) { 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results"); 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1778f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (scan_res->fetch_time.sec == 0) { 1779f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt /* 1780f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * Make sure we have a valid timestamp if the driver wrapper 1781f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * does not set this. 1782f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt */ 1783fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&scan_res->fetch_time); 1784f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 178504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt filter_scan_res(wpa_s, scan_res); 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 1788fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpas_wps_searching(wpa_s)) { 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS " 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "provisioning rules"); 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt compar = wpa_scan_result_wps_compar; 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt compar); 17971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dump_scan_res(scan_res); 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bss_update_start(wpa_s); 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < scan_res->num; i++) 1801f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_bss_update_scan_res(wpa_s, scan_res->res[i], 1802f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt &scan_res->fetch_time); 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bss_update_end(wpa_s, info, new_scan); 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return scan_res; 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1809a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/** 1810a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * wpa_supplicant_update_scan_results - Update scan results from the driver 1811a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 1812a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Returns: 0 on success, -1 on failure 1813a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * 1814a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function updates the BSS table within wpa_supplicant based on the 1815a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * currently available scan results from the driver without requesting a new 1816a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * scan. This is used in cases where the driver indicates an association 1817a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * (including roaming within ESS) and wpa_supplicant does not yet have the 1818a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * needed information to complete the connection (e.g., to perform validation 1819a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * steps in 4-way handshake). 1820a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res; 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (scan_res == NULL) 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_results_free(scan_res); 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18313a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt 18323a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt 18333a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt/** 18343a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt * scan_only_handler - Reports scan results 18353a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt */ 18363a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidtvoid scan_only_handler(struct wpa_supplicant *wpa_s, 18373a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt struct wpa_scan_results *scan_res) 18383a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt{ 18394b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received"); 1840fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && 1841fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_use_id && wpa_s->own_scan_running) { 1842fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u", 1843fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_id); 1844fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_use_id = 0; 1845fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else { 1846fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); 1847fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 18483a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt wpas_notify_scan_results(wpa_s); 18494b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt wpas_notify_scan_done(wpa_s, 1); 1850fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_s->scan_work) { 1851fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_radio_work *work = wpa_s->scan_work; 1852fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->scan_work = NULL; 1853fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt radio_work_done(work); 1854fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 18553a787e6f7c987ba5a9a56a2066467d20ab40ec58Dmitry Shmidt} 185637d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt 185737d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt 185837d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidtint wpas_scan_scheduled(struct wpa_supplicant *wpa_s) 185937d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt{ 186037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL); 186137d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt} 1862fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1863fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1864fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstruct wpa_driver_scan_params * 1865fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtwpa_scan_clone_params(const struct wpa_driver_scan_params *src) 1866fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 1867fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_scan_params *params; 1868fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt size_t i; 1869fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u8 *n; 1870fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1871fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params = os_zalloc(sizeof(*params)); 1872fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params == NULL) 1873fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return NULL; 1874fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1875fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt for (i = 0; i < src->num_ssids; i++) { 1876fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (src->ssids[i].ssid) { 1877fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt n = os_malloc(src->ssids[i].ssid_len); 1878fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (n == NULL) 1879fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto failed; 1880fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(n, src->ssids[i].ssid, 1881fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt src->ssids[i].ssid_len); 1882fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->ssids[i].ssid = n; 1883fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->ssids[i].ssid_len = src->ssids[i].ssid_len; 1884fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1885fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1886fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->num_ssids = src->num_ssids; 1887fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1888fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (src->extra_ies) { 1889fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt n = os_malloc(src->extra_ies_len); 1890fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (n == NULL) 1891fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto failed; 1892fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(n, src->extra_ies, src->extra_ies_len); 1893fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->extra_ies = n; 1894fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->extra_ies_len = src->extra_ies_len; 1895fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1896fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1897fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (src->freqs) { 1898fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int len = int_array_len(src->freqs); 1899fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->freqs = os_malloc((len + 1) * sizeof(int)); 1900fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->freqs == NULL) 1901fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto failed; 1902fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int)); 1903fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1904fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1905fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (src->filter_ssids) { 19069767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) * 1907fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt src->num_filter_ssids); 1908fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->filter_ssids == NULL) 1909fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto failed; 1910fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(params->filter_ssids, src->filter_ssids, 19119767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt sizeof(*params->filter_ssids) * 19129767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt src->num_filter_ssids); 1913fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->num_filter_ssids = src->num_filter_ssids; 1914fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1915fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1916fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->filter_rssi = src->filter_rssi; 1917fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->p2p_probe = src->p2p_probe; 1918fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->only_new_results = src->only_new_results; 19192271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt params->low_priority = src->low_priority; 1920fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1921fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return params; 1922fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1923fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtfailed: 1924fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_scan_free_params(params); 1925fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return NULL; 1926fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 1927fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1928fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1929fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtvoid wpa_scan_free_params(struct wpa_driver_scan_params *params) 1930fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 1931fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt size_t i; 1932fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1933fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params == NULL) 1934fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 1935fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 1936fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt for (i = 0; i < params->num_ssids; i++) 1937fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_free((u8 *) params->ssids[i].ssid); 1938fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_free((u8 *) params->extra_ies); 1939fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_free(params->freqs); 1940fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_free(params->filter_ssids); 1941fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_free(params); 1942fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 19439866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19449866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19459866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidtint wpas_start_pno(struct wpa_supplicant *wpa_s) 19469866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt{ 19479866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt int ret, interval; 19486aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt size_t i, num_ssid, num_match_ssid; 19499866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt struct wpa_ssid *ssid; 19509866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt struct wpa_driver_scan_params params; 19519866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19529866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (!wpa_s->sched_scan_supported) 19539866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return -1; 19549866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19559866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (wpa_s->pno || wpa_s->pno_sched_pending) 19569866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return 0; 19579866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19589866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if ((wpa_s->wpa_state > WPA_SCANNING) && 19599866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt (wpa_s->wpa_state <= WPA_COMPLETED)) { 19609866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_printf(MSG_ERROR, "PNO: In assoc process"); 19619866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return -EAGAIN; 19629866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 19639866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19649866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (wpa_s->wpa_state == WPA_SCANNING) { 19659866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_supplicant_cancel_scan(wpa_s); 19669866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (wpa_s->sched_scanning) { 19679866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_printf(MSG_DEBUG, "Schedule PNO on completion of " 19689866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt "ongoing sched scan"); 19699866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_supplicant_cancel_sched_scan(wpa_s); 19709866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_s->pno_sched_pending = 1; 19719866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return 0; 19729866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 19739866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 19749866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19759866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 19769866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 19776aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt num_ssid = num_match_ssid = 0; 19789866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ssid = wpa_s->conf->ssid; 19799866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt while (ssid) { 19806aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt if (!wpas_network_disabled(wpa_s, ssid)) { 19816aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt num_match_ssid++; 19826aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt if (ssid->scan_ssid) 19836aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt num_ssid++; 19846aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt } 19859866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ssid = ssid->next; 19869866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 19876aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt 19886aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt if (num_match_ssid == 0) { 19896aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs"); 19906aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt return -1; 19916aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt } 19926aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt 19936aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt if (num_match_ssid > num_ssid) { 19946aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt params.num_ssids++; /* wildcard */ 19956aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt num_ssid++; 19966aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt } 19976aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt 19989866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (num_ssid > WPAS_MAX_SCAN_SSIDS) { 19999866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from " 20009866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid); 20019866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt num_ssid = WPAS_MAX_SCAN_SSIDS; 20029866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 20039866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20046aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt if (num_match_ssid > wpa_s->max_match_sets) { 20056aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt num_match_ssid = wpa_s->max_match_sets; 20066aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "PNO: Too many SSIDs to match"); 20079866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 20086aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt params.filter_ssids = os_calloc(num_match_ssid, 20096aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt sizeof(struct wpa_driver_scan_filter)); 20109866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (params.filter_ssids == NULL) 20119866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return -1; 20129866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt i = 0; 20139866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ssid = wpa_s->conf->ssid; 20149866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt while (ssid) { 20159866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (!wpas_network_disabled(wpa_s, ssid)) { 20166aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt if (ssid->scan_ssid && params.num_ssids < num_ssid) { 20176aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt params.ssids[params.num_ssids].ssid = 20186aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt ssid->ssid; 20196aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt params.ssids[params.num_ssids].ssid_len = 20206aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt ssid->ssid_len; 20216aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt params.num_ssids++; 20226aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt } 20239866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt os_memcpy(params.filter_ssids[i].ssid, ssid->ssid, 20249866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ssid->ssid_len); 20259866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.filter_ssids[i].ssid_len = ssid->ssid_len; 20269866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.num_filter_ssids++; 20279866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt i++; 20286aa8ae4b6139bdf5593301474277dcdbc2528190Dmitry Shmidt if (i == num_match_ssid) 20299866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt break; 20309866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 20319866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ssid = ssid->next; 20329866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 20339866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20349866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (wpa_s->conf->filter_rssi) 20359866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt params.filter_rssi = wpa_s->conf->filter_rssi; 20369866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20379866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt interval = wpa_s->conf->sched_scan_interval ? 20389866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_s->conf->sched_scan_interval : 10; 20399866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 2040d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) { 2041d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels"); 2042d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt params.freqs = wpa_s->manual_sched_scan_freqs; 2043d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt } 2044d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 20459866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval); 20469866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt os_free(params.filter_ssids); 20479866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (ret == 0) 20489866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_s->pno = 1; 20499866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt else 20509866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO"); 20519866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return ret; 20529866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt} 20539866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20549866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20559866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidtint wpas_stop_pno(struct wpa_supplicant *wpa_s) 20569866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt{ 20579866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt int ret = 0; 20589866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20599866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (!wpa_s->pno) 20609866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return 0; 20619866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20629866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ret = wpa_supplicant_stop_sched_scan(wpa_s); 20639866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20649866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_s->pno = 0; 20659866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_s->pno_sched_pending = 0; 20669866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20679866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (wpa_s->wpa_state == WPA_SCANNING) 20689866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 20699866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 20709866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return ret; 20719866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt} 2072