LCOV - code coverage report
Current view: top level - wpa_supplicant - scan.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 627 969 64.7 %
Date: 2014-05-28 Functions: 37 45 82.2 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant - Scanning
       3             :  * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #include "utils/common.h"
      12             : #include "utils/eloop.h"
      13             : #include "common/ieee802_11_defs.h"
      14             : #include "common/wpa_ctrl.h"
      15             : #include "config.h"
      16             : #include "wpa_supplicant_i.h"
      17             : #include "driver_i.h"
      18             : #include "wps_supplicant.h"
      19             : #include "p2p_supplicant.h"
      20             : #include "p2p/p2p.h"
      21             : #include "hs20_supplicant.h"
      22             : #include "notify.h"
      23             : #include "bss.h"
      24             : #include "scan.h"
      25             : 
      26             : 
      27           2 : static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
      28             : {
      29             :         struct wpa_ssid *ssid;
      30             :         union wpa_event_data data;
      31             : 
      32           2 :         ssid = wpa_supplicant_get_ssid(wpa_s);
      33           2 :         if (ssid == NULL)
      34           3 :                 return;
      35             : 
      36           1 :         if (wpa_s->current_ssid == NULL) {
      37           0 :                 wpa_s->current_ssid = ssid;
      38           0 :                 if (wpa_s->current_ssid != NULL)
      39           0 :                         wpas_notify_network_changed(wpa_s);
      40             :         }
      41           1 :         wpa_supplicant_initiate_eapol(wpa_s);
      42           1 :         wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
      43             :                 "network - generating associated event");
      44           1 :         os_memset(&data, 0, sizeof(data));
      45           1 :         wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
      46             : }
      47             : 
      48             : 
      49             : #ifdef CONFIG_WPS
      50        1185 : static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
      51             :                            enum wps_request_type *req_type)
      52             : {
      53             :         struct wpa_ssid *ssid;
      54        1185 :         int wps = 0;
      55             : 
      56        2072 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
      57         974 :                 if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
      58         665 :                         continue;
      59             : 
      60         309 :                 wps = 1;
      61         309 :                 *req_type = wpas_wps_get_req_type(ssid);
      62         309 :                 if (!ssid->eap.phase1)
      63           0 :                         continue;
      64             : 
      65         309 :                 if (os_strstr(ssid->eap.phase1, "pbc=1"))
      66          87 :                         return 2;
      67             :         }
      68             : 
      69             : #ifdef CONFIG_P2P
      70        2194 :         if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p &&
      71        1096 :             !wpa_s->conf->p2p_disabled) {
      72        1096 :                 wpa_s->wps->dev.p2p = 1;
      73        1096 :                 if (!wps) {
      74         875 :                         wps = 1;
      75         875 :                         *req_type = WPS_REQ_ENROLLEE_INFO;
      76             :                 }
      77             :         }
      78             : #endif /* CONFIG_P2P */
      79             : 
      80        1098 :         return wps;
      81             : }
      82             : #endif /* CONFIG_WPS */
      83             : 
      84             : 
      85             : /**
      86             :  * wpa_supplicant_enabled_networks - Check whether there are enabled networks
      87             :  * @wpa_s: Pointer to wpa_supplicant data
      88             :  * Returns: 0 if no networks are enabled, >0 if networks are enabled
      89             :  *
      90             :  * This function is used to figure out whether any networks (or Interworking
      91             :  * with enabled credentials and auto_interworking) are present in the current
      92             :  * configuration.
      93             :  */
      94        2555 : int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
      95             : {
      96        2555 :         struct wpa_ssid *ssid = wpa_s->conf->ssid;
      97        2555 :         int count = 0, disabled = 0;
      98        6839 :         while (ssid) {
      99        1729 :                 if (!wpas_network_disabled(wpa_s, ssid))
     100        1661 :                         count++;
     101             :                 else
     102          68 :                         disabled++;
     103        1729 :                 ssid = ssid->next;
     104             :         }
     105        2804 :         if (wpa_s->conf->cred && wpa_s->conf->interworking &&
     106         249 :             wpa_s->conf->auto_interworking)
     107           1 :                 count++;
     108        2555 :         if (count == 0 && disabled > 0) {
     109           4 :                 wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled "
     110             :                         "networks)", disabled);
     111             :         }
     112        2555 :         return count;
     113             : }
     114             : 
     115             : 
     116           4 : static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
     117             :                                      struct wpa_ssid *ssid)
     118             : {
     119           8 :         while (ssid) {
     120           4 :                 if (!wpas_network_disabled(wpa_s, ssid))
     121           4 :                         break;
     122           0 :                 ssid = ssid->next;
     123             :         }
     124             : 
     125             :         /* ap_scan=2 mode - try to associate with each SSID. */
     126           4 :         if (ssid == NULL) {
     127           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached "
     128             :                         "end of scan list - go back to beginning");
     129           0 :                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
     130           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
     131           4 :                 return;
     132             :         }
     133           4 :         if (ssid->next) {
     134             :                 /* Continue from the next SSID on the next attempt. */
     135           0 :                 wpa_s->prev_scan_ssid = ssid;
     136             :         } else {
     137             :                 /* Start from the beginning of the SSID list. */
     138           4 :                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
     139             :         }
     140           4 :         wpa_supplicant_associate(wpa_s, NULL, ssid);
     141             : }
     142             : 
     143             : 
     144        1201 : static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
     145             : {
     146        1201 :         struct wpa_supplicant *wpa_s = work->wpa_s;
     147        1201 :         struct wpa_driver_scan_params *params = work->ctx;
     148             :         int ret;
     149             : 
     150        1201 :         if (deinit) {
     151           4 :                 if (!work->started) {
     152           0 :                         wpa_scan_free_params(params);
     153           0 :                         return;
     154             :                 }
     155           4 :                 wpa_supplicant_notify_scanning(wpa_s, 0);
     156           4 :                 wpas_notify_scan_done(wpa_s, 0);
     157           4 :                 wpa_s->scan_work = NULL;
     158           4 :                 return;
     159             :         }
     160             : 
     161        1197 :         wpa_supplicant_notify_scanning(wpa_s, 1);
     162             : 
     163        1197 :         if (wpa_s->clear_driver_scan_cache)
     164         734 :                 params->only_new_results = 1;
     165        1197 :         ret = wpa_drv_scan(wpa_s, params);
     166        1197 :         wpa_scan_free_params(params);
     167        1197 :         work->ctx = NULL;
     168        1197 :         if (ret) {
     169           1 :                 wpa_supplicant_notify_scanning(wpa_s, 0);
     170           1 :                 wpas_notify_scan_done(wpa_s, 0);
     171           1 :                 radio_work_done(work);
     172           1 :                 return;
     173             :         }
     174             : 
     175        1196 :         os_get_reltime(&wpa_s->scan_trigger_time);
     176        1196 :         wpa_s->scan_runs++;
     177        1196 :         wpa_s->normal_scans++;
     178        1196 :         wpa_s->own_scan_requested = 1;
     179        1196 :         wpa_s->clear_driver_scan_cache = 0;
     180        1196 :         wpa_s->scan_work = work;
     181             : }
     182             : 
     183             : 
     184             : /**
     185             :  * wpa_supplicant_trigger_scan - Request driver to start a scan
     186             :  * @wpa_s: Pointer to wpa_supplicant data
     187             :  * @params: Scan parameters
     188             :  * Returns: 0 on success, -1 on failure
     189             :  */
     190        1197 : int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
     191             :                                 struct wpa_driver_scan_params *params)
     192             : {
     193             :         struct wpa_driver_scan_params *ctx;
     194             : 
     195        1197 :         if (wpa_s->scan_work) {
     196           0 :                 wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending");
     197           0 :                 return -1;
     198             :         }
     199             : 
     200        1197 :         ctx = wpa_scan_clone_params(params);
     201        1197 :         if (ctx == NULL)
     202           0 :                 return -1;
     203             : 
     204        1197 :         if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
     205             :         {
     206           0 :                 wpa_scan_free_params(ctx);
     207           0 :                 return -1;
     208             :         }
     209             : 
     210        1197 :         return 0;
     211             : }
     212             : 
     213             : 
     214             : static void
     215           0 : wpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
     216             : {
     217           0 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     218             : 
     219           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan");
     220             : 
     221           0 :         if (wpa_supplicant_req_sched_scan(wpa_s))
     222           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
     223           0 : }
     224             : 
     225             : 
     226             : static void
     227           0 : wpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
     228             : {
     229           0 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     230             : 
     231           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it");
     232             : 
     233           0 :         wpa_s->sched_scan_timed_out = 1;
     234           0 :         wpa_supplicant_cancel_sched_scan(wpa_s);
     235           0 : }
     236             : 
     237             : 
     238           0 : int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
     239             :                                     struct wpa_driver_scan_params *params,
     240             :                                     int interval)
     241             : {
     242             :         int ret;
     243             : 
     244           0 :         wpa_supplicant_notify_scanning(wpa_s, 1);
     245           0 :         ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
     246           0 :         if (ret)
     247           0 :                 wpa_supplicant_notify_scanning(wpa_s, 0);
     248             :         else
     249           0 :                 wpa_s->sched_scanning = 1;
     250             : 
     251           0 :         return ret;
     252             : }
     253             : 
     254             : 
     255           0 : int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
     256             : {
     257             :         int ret;
     258             : 
     259           0 :         ret = wpa_drv_stop_sched_scan(wpa_s);
     260           0 :         if (ret) {
     261           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!");
     262             :                 /* TODO: what to do if stopping fails? */
     263           0 :                 return -1;
     264             :         }
     265             : 
     266           0 :         return ret;
     267             : }
     268             : 
     269             : 
     270             : static struct wpa_driver_scan_filter *
     271        1185 : wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
     272             : {
     273             :         struct wpa_driver_scan_filter *ssids;
     274             :         struct wpa_ssid *ssid;
     275             :         size_t count;
     276             : 
     277        1185 :         *num_ssids = 0;
     278        1185 :         if (!conf->filter_ssids)
     279        1184 :                 return NULL;
     280             : 
     281           2 :         for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
     282           1 :                 if (ssid->ssid && ssid->ssid_len)
     283           1 :                         count++;
     284             :         }
     285           1 :         if (count == 0)
     286           0 :                 return NULL;
     287           1 :         ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter));
     288           1 :         if (ssids == NULL)
     289           0 :                 return NULL;
     290             : 
     291           2 :         for (ssid = conf->ssid; ssid; ssid = ssid->next) {
     292           1 :                 if (!ssid->ssid || !ssid->ssid_len)
     293           0 :                         continue;
     294           1 :                 os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
     295           1 :                 ssids[*num_ssids].ssid_len = ssid->ssid_len;
     296           1 :                 (*num_ssids)++;
     297             :         }
     298             : 
     299           1 :         return ssids;
     300             : }
     301             : 
     302             : 
     303        1185 : static void wpa_supplicant_optimize_freqs(
     304             :         struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params)
     305             : {
     306             : #ifdef CONFIG_P2P
     307        1340 :         if (params->freqs == NULL && wpa_s->p2p_in_provisioning &&
     308         155 :             wpa_s->go_params) {
     309             :                 /* Optimize provisioning state scan based on GO information */
     310         305 :                 if (wpa_s->p2p_in_provisioning < 5 &&
     311         151 :                     wpa_s->go_params->freq > 0) {
     312         151 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO "
     313             :                                 "preferred frequency %d MHz",
     314             :                                 wpa_s->go_params->freq);
     315         151 :                         params->freqs = os_zalloc(2 * sizeof(int));
     316         302 :                         if (params->freqs)
     317         151 :                                 params->freqs[0] = wpa_s->go_params->freq;
     318           6 :                 } else if (wpa_s->p2p_in_provisioning < 8 &&
     319           3 :                            wpa_s->go_params->freq_list[0]) {
     320           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common "
     321             :                                 "channels");
     322           0 :                         int_array_concat(&params->freqs,
     323           0 :                                          wpa_s->go_params->freq_list);
     324           0 :                         if (params->freqs)
     325           0 :                                 int_array_sort_unique(params->freqs);
     326             :                 }
     327         154 :                 wpa_s->p2p_in_provisioning++;
     328             :         }
     329             : 
     330        1185 :         if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
     331             :                 /*
     332             :                  * Optimize scan based on GO information during persistent
     333             :                  * group reinvocation
     334             :                  */
     335          18 :                 if (wpa_s->p2p_in_invitation < 5 &&
     336           9 :                     wpa_s->p2p_invite_go_freq > 0) {
     337           7 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
     338             :                                 wpa_s->p2p_invite_go_freq);
     339           7 :                         params->freqs = os_zalloc(2 * sizeof(int));
     340           7 :                         if (params->freqs)
     341           7 :                                 params->freqs[0] = wpa_s->p2p_invite_go_freq;
     342             :                 }
     343           9 :                 wpa_s->p2p_in_invitation++;
     344           9 :                 if (wpa_s->p2p_in_invitation > 20) {
     345             :                         /*
     346             :                          * This should not really happen since the variable is
     347             :                          * cleared on group removal, but if it does happen, make
     348             :                          * sure we do not get stuck in special invitation scan
     349             :                          * mode.
     350             :                          */
     351           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
     352           0 :                         wpa_s->p2p_in_invitation = 0;
     353             :                 }
     354             :         }
     355             : #endif /* CONFIG_P2P */
     356             : 
     357             : #ifdef CONFIG_WPS
     358        1185 :         if (params->freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
     359             :                 /*
     360             :                  * Optimize post-provisioning scan based on channel used
     361             :                  * during provisioning.
     362             :                  */
     363          32 :                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz "
     364             :                         "that was used during provisioning", wpa_s->wps_freq);
     365          32 :                 params->freqs = os_zalloc(2 * sizeof(int));
     366          32 :                 if (params->freqs)
     367          32 :                         params->freqs[0] = wpa_s->wps_freq;
     368          32 :                 wpa_s->after_wps--;
     369        1153 :         } else if (wpa_s->after_wps)
     370           1 :                 wpa_s->after_wps--;
     371             : 
     372        1185 :         if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
     373             :         {
     374             :                 /* Optimize provisioning scan based on already known channel */
     375          17 :                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz",
     376             :                         wpa_s->wps_freq);
     377          17 :                 params->freqs = os_zalloc(2 * sizeof(int));
     378          17 :                 if (params->freqs)
     379          17 :                         params->freqs[0] = wpa_s->wps_freq;
     380          17 :                 wpa_s->known_wps_freq = 0; /* only do this once */
     381             :         }
     382             : #endif /* CONFIG_WPS */
     383        1185 : }
     384             : 
     385             : 
     386             : #ifdef CONFIG_INTERWORKING
     387         298 : static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
     388             :                                            struct wpabuf *buf)
     389             : {
     390         298 :         if (wpa_s->conf->interworking == 0)
     391         298 :                 return;
     392             : 
     393         298 :         wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB);
     394         298 :         wpabuf_put_u8(buf, 6);
     395         298 :         wpabuf_put_u8(buf, 0x00);
     396         298 :         wpabuf_put_u8(buf, 0x00);
     397         298 :         wpabuf_put_u8(buf, 0x00);
     398         298 :         wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */
     399         298 :         wpabuf_put_u8(buf, 0x00);
     400             : #ifdef CONFIG_HS20
     401         298 :         wpabuf_put_u8(buf, 0x40); /* Bit 46 - WNM-Notification */
     402             : #else /* CONFIG_HS20 */
     403             :         wpabuf_put_u8(buf, 0x00);
     404             : #endif /* CONFIG_HS20 */
     405             : 
     406         298 :         wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
     407         298 :         wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
     408             :                       1 + ETH_ALEN);
     409         298 :         wpabuf_put_u8(buf, wpa_s->conf->access_network_type);
     410             :         /* No Venue Info */
     411         298 :         if (!is_zero_ether_addr(wpa_s->conf->hessid))
     412           4 :                 wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN);
     413             : }
     414             : #endif /* CONFIG_INTERWORKING */
     415             : 
     416             : 
     417        1185 : static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
     418             : {
     419        1185 :         struct wpabuf *extra_ie = NULL;
     420             : #ifdef CONFIG_WPS
     421        1185 :         int wps = 0;
     422        1185 :         enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
     423             : #endif /* CONFIG_WPS */
     424             : 
     425             : #ifdef CONFIG_INTERWORKING
     426        1483 :         if (wpa_s->conf->interworking &&
     427         298 :             wpabuf_resize(&extra_ie, 100) == 0)
     428         298 :                 wpas_add_interworking_elements(wpa_s, extra_ie);
     429             : #endif /* CONFIG_INTERWORKING */
     430             : 
     431             : #ifdef CONFIG_WPS
     432        1185 :         wps = wpas_wps_in_use(wpa_s, &req_type);
     433             : 
     434        1185 :         if (wps) {
     435             :                 struct wpabuf *wps_ie;
     436        2368 :                 wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
     437             :                                                 DEV_PW_DEFAULT,
     438        1184 :                                                 &wpa_s->wps->dev,
     439        1184 :                                                 wpa_s->wps->uuid, req_type,
     440             :                                                 0, NULL);
     441        1184 :                 if (wps_ie) {
     442        1184 :                         if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
     443        1184 :                                 wpabuf_put_buf(extra_ie, wps_ie);
     444        1184 :                         wpabuf_free(wps_ie);
     445             :                 }
     446             :         }
     447             : 
     448             : #ifdef CONFIG_P2P
     449        1185 :         if (wps) {
     450        1184 :                 size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
     451        1184 :                 if (wpabuf_resize(&extra_ie, ielen) == 0)
     452        1184 :                         wpas_p2p_scan_ie(wpa_s, extra_ie);
     453             :         }
     454             : #endif /* CONFIG_P2P */
     455             : 
     456             : #endif /* CONFIG_WPS */
     457             : 
     458             : #ifdef CONFIG_HS20
     459        1185 :         if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
     460         298 :                 wpas_hs20_add_indication(extra_ie, -1);
     461             : #endif /* CONFIG_HS20 */
     462             : 
     463        1185 :         return extra_ie;
     464             : }
     465             : 
     466             : 
     467             : #ifdef CONFIG_P2P
     468             : 
     469             : /*
     470             :  * Check whether there are any enabled networks or credentials that could be
     471             :  * used for a non-P2P connection.
     472             :  */
     473          58 : static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
     474             : {
     475             :         struct wpa_ssid *ssid;
     476             : 
     477          58 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
     478          58 :                 if (wpas_network_disabled(wpa_s, ssid))
     479           0 :                         continue;
     480          58 :                 if (!ssid->p2p_group)
     481          58 :                         return 1;
     482             :         }
     483             : 
     484           0 :         if (wpa_s->conf->cred && wpa_s->conf->interworking &&
     485           0 :             wpa_s->conf->auto_interworking)
     486           0 :                 return 1;
     487             : 
     488           0 :         return 0;
     489             : }
     490             : 
     491             : #endif /* CONFIG_P2P */
     492             : 
     493             : 
     494           0 : static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
     495             :                                           u16 num_modes,
     496             :                                           enum hostapd_hw_mode mode)
     497             : {
     498             :         u16 i;
     499             : 
     500           0 :         for (i = 0; i < num_modes; i++) {
     501           0 :                 if (modes[i].mode == mode)
     502           0 :                         return &modes[i];
     503             :         }
     504             : 
     505           0 :         return NULL;
     506             : }
     507             : 
     508             : 
     509           0 : static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
     510             :                                         enum hostapd_hw_mode band,
     511             :                                         struct wpa_driver_scan_params *params)
     512             : {
     513             :         /* Include only supported channels for the specified band */
     514             :         struct hostapd_hw_modes *mode;
     515             :         int count, i;
     516             : 
     517           0 :         mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
     518           0 :         if (mode == NULL) {
     519             :                 /* No channels supported in this band - use empty list */
     520           0 :                 params->freqs = os_zalloc(sizeof(int));
     521           0 :                 return;
     522             :         }
     523             : 
     524           0 :         params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int));
     525           0 :         if (params->freqs == NULL)
     526           0 :                 return;
     527           0 :         for (count = 0, i = 0; i < mode->num_channels; i++) {
     528           0 :                 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
     529           0 :                         continue;
     530           0 :                 params->freqs[count++] = mode->channels[i].freq;
     531             :         }
     532             : }
     533             : 
     534             : 
     535        1185 : static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
     536             :                                    struct wpa_driver_scan_params *params)
     537             : {
     538        1185 :         if (wpa_s->hw.modes == NULL)
     539           0 :                 return; /* unknown what channels the driver supports */
     540        1185 :         if (params->freqs)
     541        1009 :                 return; /* already using a limited channel set */
     542         176 :         if (wpa_s->setband == WPA_SETBAND_5G)
     543           0 :                 wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
     544             :                                             params);
     545         176 :         else if (wpa_s->setband == WPA_SETBAND_2G)
     546           0 :                 wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
     547             :                                             params);
     548             : }
     549             : 
     550             : 
     551        1795 : static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
     552             : {
     553        1795 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     554             :         struct wpa_ssid *ssid;
     555             :         int ret;
     556        1795 :         struct wpabuf *extra_ie = NULL;
     557             :         struct wpa_driver_scan_params params;
     558             :         struct wpa_driver_scan_params *scan_params;
     559             :         size_t max_ssids;
     560             :         enum wpa_states prev_state;
     561             : 
     562        1795 :         if (wpa_s->pno || wpa_s->pno_sched_pending) {
     563           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
     564           0 :                 return;
     565             :         }
     566             : 
     567        1795 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
     568           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
     569           0 :                 return;
     570             :         }
     571             : 
     572        1795 :         if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
     573           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
     574           0 :                 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
     575           0 :                 return;
     576             :         }
     577             : 
     578        1795 :         if (wpa_s->scanning) {
     579             :                 /*
     580             :                  * If we are already in scanning state, we shall reschedule the
     581             :                  * the incoming scan request.
     582             :                  */
     583           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req");
     584           0 :                 wpa_supplicant_req_scan(wpa_s, 1, 0);
     585           0 :                 return;
     586             :         }
     587             : 
     588        2513 :         if (!wpa_supplicant_enabled_networks(wpa_s) &&
     589         718 :             wpa_s->scan_req == NORMAL_SCAN_REQ) {
     590         485 :                 wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
     591         485 :                 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
     592         485 :                 return;
     593             :         }
     594             : 
     595        2618 :         if (wpa_s->conf->ap_scan != 0 &&
     596        1308 :             (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
     597           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - "
     598             :                         "overriding ap_scan configuration");
     599           0 :                 wpa_s->conf->ap_scan = 0;
     600           0 :                 wpas_notify_ap_scan_changed(wpa_s);
     601             :         }
     602             : 
     603        1310 :         if (wpa_s->conf->ap_scan == 0) {
     604           2 :                 wpa_supplicant_gen_assoc_event(wpa_s);
     605           2 :                 return;
     606             :         }
     607             : 
     608             : #ifdef CONFIG_P2P
     609        1308 :         if (wpas_p2p_in_progress(wpa_s)) {
     610           1 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
     611           1 :                 wpa_supplicant_req_scan(wpa_s, 5, 0);
     612           1 :                 return;
     613             :         }
     614             : #endif /* CONFIG_P2P */
     615             : 
     616        1307 :         if (wpa_s->conf->ap_scan == 2)
     617           4 :                 max_ssids = 1;
     618             :         else {
     619        1303 :                 max_ssids = wpa_s->max_scan_ssids;
     620        1303 :                 if (max_ssids > WPAS_MAX_SCAN_SSIDS)
     621           0 :                         max_ssids = WPAS_MAX_SCAN_SSIDS;
     622             :         }
     623             : 
     624        1307 :         wpa_s->last_scan_req = wpa_s->scan_req;
     625        1307 :         wpa_s->scan_req = NORMAL_SCAN_REQ;
     626             : 
     627        1307 :         os_memset(&params, 0, sizeof(params));
     628             : 
     629        1307 :         prev_state = wpa_s->wpa_state;
     630        2106 :         if (wpa_s->wpa_state == WPA_DISCONNECTED ||
     631         799 :             wpa_s->wpa_state == WPA_INACTIVE)
     632        1091 :                 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
     633             : 
     634             :         /*
     635             :          * If autoscan has set its own scanning parameters
     636             :          */
     637        1307 :         if (wpa_s->autoscan_params != NULL) {
     638           0 :                 scan_params = wpa_s->autoscan_params;
     639           0 :                 goto scan;
     640             :         }
     641             : 
     642        2330 :         if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
     643        1023 :             wpa_s->connect_without_scan) {
     644         135 :                 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
     645         135 :                         if (ssid == wpa_s->connect_without_scan)
     646         118 :                                 break;
     647             :                 }
     648         118 :                 wpa_s->connect_without_scan = NULL;
     649         118 :                 if (ssid) {
     650         118 :                         wpa_printf(MSG_DEBUG, "Start a pre-selected network "
     651             :                                    "without scan step");
     652         118 :                         wpa_supplicant_associate(wpa_s, NULL, ssid);
     653         118 :                         return;
     654             :                 }
     655             :         }
     656             : 
     657             : #ifdef CONFIG_P2P
     658        1353 :         if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
     659         164 :             wpa_s->go_params) {
     660         154 :                 wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)",
     661             :                            wpa_s->p2p_in_provisioning,
     662             :                            wpa_s->show_group_started);
     663         154 :                 params.ssids[0].ssid = wpa_s->go_params->ssid;
     664         154 :                 params.ssids[0].ssid_len = wpa_s->go_params->ssid_len;
     665         154 :                 params.num_ssids = 1;
     666         154 :                 goto ssid_list_set;
     667             :         }
     668             : 
     669        1035 :         if (wpa_s->p2p_in_invitation) {
     670           9 :                 if (wpa_s->current_ssid) {
     671           4 :                         wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation");
     672           4 :                         params.ssids[0].ssid = wpa_s->current_ssid->ssid;
     673           4 :                         params.ssids[0].ssid_len =
     674           4 :                                 wpa_s->current_ssid->ssid_len;
     675           4 :                         params.num_ssids = 1;
     676             :                 } else {
     677           5 :                         wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation");
     678             :                 }
     679           9 :                 goto ssid_list_set;
     680             :         }
     681             : #endif /* CONFIG_P2P */
     682             : 
     683             :         /* Find the starting point from which to continue scanning */
     684        1026 :         ssid = wpa_s->conf->ssid;
     685        1026 :         if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
     686           2 :                 while (ssid) {
     687           1 :                         if (ssid == wpa_s->prev_scan_ssid) {
     688           1 :                                 ssid = ssid->next;
     689           1 :                                 break;
     690             :                         }
     691           0 :                         ssid = ssid->next;
     692             :                 }
     693             :         }
     694             : 
     695        1768 :         if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
     696         742 :             wpa_s->conf->ap_scan == 2) {
     697           4 :                 wpa_s->connect_without_scan = NULL;
     698           4 :                 wpa_s->prev_scan_wildcard = 0;
     699           4 :                 wpa_supplicant_assoc_try(wpa_s, ssid);
     700           4 :                 return;
     701        1022 :         } else if (wpa_s->conf->ap_scan == 2) {
     702             :                 /*
     703             :                  * User-initiated scan request in ap_scan == 2; scan with
     704             :                  * wildcard SSID.
     705             :                  */
     706           0 :                 ssid = NULL;
     707        1022 :         } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
     708             :                 /*
     709             :                  * Perform single-channel single-SSID scan for
     710             :                  * reassociate-to-same-BSS operation.
     711             :                  */
     712             :                 /* Setup SSID */
     713           1 :                 ssid = wpa_s->current_ssid;
     714           2 :                 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
     715           1 :                                   ssid->ssid, ssid->ssid_len);
     716           1 :                 params.ssids[0].ssid = ssid->ssid;
     717           1 :                 params.ssids[0].ssid_len = ssid->ssid_len;
     718           1 :                 params.num_ssids = 1;
     719             : 
     720             :                 /*
     721             :                  * Allocate memory for frequency array, allocate one extra
     722             :                  * slot for the zero-terminator.
     723             :                  */
     724           1 :                 params.freqs = os_malloc(sizeof(int) * 2);
     725           1 :                 if (params.freqs == NULL) {
     726           0 :                         wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
     727           0 :                         return;
     728             :                 }
     729           1 :                 params.freqs[0] = wpa_s->assoc_freq;
     730           1 :                 params.freqs[1] = 0;
     731             : 
     732             :                 /*
     733             :                  * Reset the reattach flag so that we fall back to full scan if
     734             :                  * this scan fails.
     735             :                  */
     736           1 :                 wpa_s->reattach = 0;
     737             :         } else {
     738        1021 :                 struct wpa_ssid *start = ssid, *tssid;
     739        1021 :                 int freqs_set = 0;
     740        1021 :                 if (ssid == NULL && max_ssids > 1)
     741         233 :                         ssid = wpa_s->conf->ssid;
     742        2841 :                 while (ssid) {
     743        1591 :                         if (!wpas_network_disabled(wpa_s, ssid) &&
     744         791 :                             ssid->scan_ssid) {
     745           6 :                                 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
     746           3 :                                                   ssid->ssid, ssid->ssid_len);
     747           6 :                                 params.ssids[params.num_ssids].ssid =
     748           3 :                                         ssid->ssid;
     749           6 :                                 params.ssids[params.num_ssids].ssid_len =
     750           3 :                                         ssid->ssid_len;
     751           3 :                                 params.num_ssids++;
     752           3 :                                 if (params.num_ssids + 1 >= max_ssids)
     753           0 :                                         break;
     754             :                         }
     755         800 :                         ssid = ssid->next;
     756         800 :                         if (ssid == start)
     757           1 :                                 break;
     758        1587 :                         if (ssid == NULL && max_ssids > 1 &&
     759         788 :                             start != wpa_s->conf->ssid)
     760           0 :                                 ssid = wpa_s->conf->ssid;
     761             :                 }
     762             : 
     763        1821 :                 for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) {
     764         800 :                         if (wpas_network_disabled(wpa_s, tssid))
     765           9 :                                 continue;
     766         791 :                         if ((params.freqs || !freqs_set) && tssid->scan_freq) {
     767         536 :                                 int_array_concat(&params.freqs,
     768         536 :                                                  tssid->scan_freq);
     769             :                         } else {
     770         255 :                                 os_free(params.freqs);
     771         255 :                                 params.freqs = NULL;
     772             :                         }
     773         791 :                         freqs_set = 1;
     774             :                 }
     775        1021 :                 int_array_sort_unique(params.freqs);
     776             :         }
     777             : 
     778        1022 :         if (ssid && max_ssids == 1) {
     779             :                 /*
     780             :                  * If the driver is limited to 1 SSID at a time interleave
     781             :                  * wildcard SSID scans with specific SSID scans to avoid
     782             :                  * waiting a long time for a wildcard scan.
     783             :                  */
     784           0 :                 if (!wpa_s->prev_scan_wildcard) {
     785           0 :                         params.ssids[0].ssid = NULL;
     786           0 :                         params.ssids[0].ssid_len = 0;
     787           0 :                         wpa_s->prev_scan_wildcard = 1;
     788           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for "
     789             :                                 "wildcard SSID (Interleave with specific)");
     790             :                 } else {
     791           0 :                         wpa_s->prev_scan_ssid = ssid;
     792           0 :                         wpa_s->prev_scan_wildcard = 0;
     793           0 :                         wpa_dbg(wpa_s, MSG_DEBUG,
     794             :                                 "Starting AP scan for specific SSID: %s",
     795             :                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
     796             :                 }
     797        1022 :         } else if (ssid) {
     798             :                 /* max_ssids > 1 */
     799             : 
     800           1 :                 wpa_s->prev_scan_ssid = ssid;
     801           1 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
     802             :                         "the scan request");
     803           1 :                 params.num_ssids++;
     804        1021 :         } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
     805           2 :                    wpa_s->manual_scan_passive && params.num_ssids == 0) {
     806           2 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request");
     807             :         } else {
     808        1019 :                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
     809        1019 :                 params.num_ssids++;
     810        1019 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard "
     811             :                         "SSID");
     812             :         }
     813             : #ifdef CONFIG_P2P
     814             : ssid_list_set:
     815             : #endif /* CONFIG_P2P */
     816             : 
     817        1185 :         wpa_supplicant_optimize_freqs(wpa_s, &params);
     818        1185 :         extra_ie = wpa_supplicant_extra_ies(wpa_s);
     819             : 
     820        1185 :         if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
     821             :             wpa_s->manual_scan_only_new)
     822          11 :                 params.only_new_results = 1;
     823             : 
     824        1450 :         if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
     825         265 :             wpa_s->manual_scan_freqs) {
     826         251 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
     827         251 :                 params.freqs = wpa_s->manual_scan_freqs;
     828         251 :                 wpa_s->manual_scan_freqs = NULL;
     829             :         }
     830             : 
     831        1185 :         if (params.freqs == NULL && wpa_s->next_scan_freqs) {
     832          16 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
     833             :                         "generated frequency list");
     834          16 :                 params.freqs = wpa_s->next_scan_freqs;
     835             :         } else
     836        1169 :                 os_free(wpa_s->next_scan_freqs);
     837        1185 :         wpa_s->next_scan_freqs = NULL;
     838        1185 :         wpa_setband_scan_freqs(wpa_s, &params);
     839             : 
     840             :         /* See if user specified frequencies. If so, scan only those. */
     841        1185 :         if (wpa_s->conf->freq_list && !params.freqs) {
     842           0 :                 wpa_dbg(wpa_s, MSG_DEBUG,
     843             :                         "Optimize scan based on conf->freq_list");
     844           0 :                 int_array_concat(&params.freqs, wpa_s->conf->freq_list);
     845             :         }
     846             : 
     847             :         /* Use current associated channel? */
     848        1185 :         if (wpa_s->conf->scan_cur_freq && !params.freqs) {
     849           0 :                 unsigned int num = wpa_s->num_multichan_concurrent;
     850             : 
     851           0 :                 params.freqs = os_calloc(num + 1, sizeof(int));
     852           0 :                 if (params.freqs) {
     853           0 :                         num = get_shared_radio_freqs(wpa_s, params.freqs, num);
     854           0 :                         if (num > 0) {
     855           0 :                                 wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
     856             :                                         "current operating channels since "
     857             :                                         "scan_cur_freq is enabled");
     858             :                         } else {
     859           0 :                                 os_free(params.freqs);
     860           0 :                                 params.freqs = NULL;
     861             :                         }
     862             :                 }
     863             :         }
     864             : 
     865        1185 :         params.filter_ssids = wpa_supplicant_build_filter_ssids(
     866             :                 wpa_s->conf, &params.num_filter_ssids);
     867        1185 :         if (extra_ie) {
     868        1184 :                 params.extra_ies = wpabuf_head(extra_ie);
     869        1184 :                 params.extra_ies_len = wpabuf_len(extra_ie);
     870             :         }
     871             : 
     872             : #ifdef CONFIG_P2P
     873        2206 :         if (wpa_s->p2p_in_provisioning || wpa_s->p2p_in_invitation ||
     874        1021 :             (wpa_s->show_group_started && wpa_s->go_params)) {
     875             :                 /*
     876             :                  * The interface may not yet be in P2P mode, so we have to
     877             :                  * explicitly request P2P probe to disable CCK rates.
     878             :                  */
     879         164 :                 params.p2p_probe = 1;
     880             :         }
     881             : #endif /* CONFIG_P2P */
     882             : 
     883        1185 :         scan_params = &params;
     884             : 
     885             : scan:
     886             : #ifdef CONFIG_P2P
     887             :         /*
     888             :          * If the driver does not support multi-channel concurrency and a
     889             :          * virtual interface that shares the same radio with the wpa_s interface
     890             :          * is operating there may not be need to scan other channels apart from
     891             :          * the current operating channel on the other virtual interface. Filter
     892             :          * out other channels in case we are trying to find a connection for a
     893             :          * station interface when we are not configured to prefer station
     894             :          * connection and a concurrent operation is already in process.
     895             :          */
     896        1374 :         if (wpa_s->scan_for_connection &&
     897         368 :             wpa_s->last_scan_req == NORMAL_SCAN_REQ &&
     898         295 :             !scan_params->freqs && !params.freqs &&
     899         116 :             wpas_is_p2p_prioritized(wpa_s) &&
     900         116 :             wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
     901          58 :             non_p2p_network_enabled(wpa_s)) {
     902          58 :                 unsigned int num = wpa_s->num_multichan_concurrent;
     903             : 
     904          58 :                 params.freqs = os_calloc(num + 1, sizeof(int));
     905          58 :                 if (params.freqs) {
     906          58 :                         num = get_shared_radio_freqs(wpa_s, params.freqs, num);
     907          58 :                         if (num > 0 && num == wpa_s->num_multichan_concurrent) {
     908           0 :                                 wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used");
     909             :                         } else {
     910          58 :                                 os_free(params.freqs);
     911          58 :                                 params.freqs = NULL;
     912             :                         }
     913             :                 }
     914             :         }
     915             : #endif /* CONFIG_P2P */
     916             : 
     917        1185 :         ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
     918             : 
     919        1185 :         if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
     920           0 :             !wpa_s->manual_scan_freqs) {
     921             :                 /* Restore manual_scan_freqs for the next attempt */
     922           0 :                 wpa_s->manual_scan_freqs = params.freqs;
     923           0 :                 params.freqs = NULL;
     924             :         }
     925             : 
     926        1185 :         wpabuf_free(extra_ie);
     927        1185 :         os_free(params.freqs);
     928        1185 :         os_free(params.filter_ssids);
     929             : 
     930        1185 :         if (ret) {
     931           0 :                 wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
     932           0 :                 if (prev_state != wpa_s->wpa_state)
     933           0 :                         wpa_supplicant_set_state(wpa_s, prev_state);
     934             :                 /* Restore scan_req since we will try to scan again */
     935           0 :                 wpa_s->scan_req = wpa_s->last_scan_req;
     936           0 :                 wpa_supplicant_req_scan(wpa_s, 1, 0);
     937             :         } else {
     938        1185 :                 wpa_s->scan_for_connection = 0;
     939             :         }
     940             : }
     941             : 
     942             : 
     943           2 : void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec)
     944             : {
     945             :         struct os_reltime remaining, new_int;
     946             :         int cancelled;
     947             : 
     948           2 :         cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL,
     949             :                                              &remaining);
     950             : 
     951           2 :         new_int.sec = sec;
     952           2 :         new_int.usec = 0;
     953           2 :         if (cancelled && os_reltime_before(&remaining, &new_int)) {
     954           1 :                 new_int.sec = remaining.sec;
     955           1 :                 new_int.usec = remaining.usec;
     956             :         }
     957             : 
     958           2 :         if (cancelled) {
     959           1 :                 eloop_register_timeout(new_int.sec, new_int.usec,
     960             :                                        wpa_supplicant_scan, wpa_s, NULL);
     961             :         }
     962           2 :         wpa_s->scan_interval = sec;
     963           2 : }
     964             : 
     965             : 
     966             : /**
     967             :  * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
     968             :  * @wpa_s: Pointer to wpa_supplicant data
     969             :  * @sec: Number of seconds after which to scan
     970             :  * @usec: Number of microseconds after which to scan
     971             :  *
     972             :  * This function is used to schedule a scan for neighboring access points after
     973             :  * the specified time.
     974             :  */
     975        3062 : void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
     976             : {
     977        3062 :         int res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
     978             :                                         NULL);
     979        3062 :         if (res == 1) {
     980          89 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d.%06d sec",
     981             :                         sec, usec);
     982        2973 :         } else if (res == 0) {
     983         878 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner",
     984             :                         sec, usec);
     985             :         } else {
     986        2095 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d.%06d sec",
     987             :                         sec, usec);
     988        2095 :                 eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
     989             :         }
     990        3062 : }
     991             : 
     992             : 
     993             : /**
     994             :  * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan
     995             :  * @wpa_s: Pointer to wpa_supplicant data
     996             :  * @sec: Number of seconds after which to scan
     997             :  * @usec: Number of microseconds after which to scan
     998             :  * Returns: 0 on success or -1 otherwise
     999             :  *
    1000             :  * This function is used to schedule periodic scans for neighboring
    1001             :  * access points after the specified time.
    1002             :  */
    1003           0 : int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
    1004             :                                       int sec, int usec)
    1005             : {
    1006           0 :         if (!wpa_s->sched_scan_supported)
    1007           0 :                 return -1;
    1008             : 
    1009           0 :         eloop_register_timeout(sec, usec,
    1010             :                                wpa_supplicant_delayed_sched_scan_timeout,
    1011             :                                wpa_s, NULL);
    1012             : 
    1013           0 :         return 0;
    1014             : }
    1015             : 
    1016             : 
    1017             : /**
    1018             :  * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
    1019             :  * @wpa_s: Pointer to wpa_supplicant data
    1020             :  * Returns: 0 is sched_scan was started or -1 otherwise
    1021             :  *
    1022             :  * This function is used to schedule periodic scans for neighboring
    1023             :  * access points repeating the scan continuously.
    1024             :  */
    1025         205 : int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
    1026             : {
    1027             :         struct wpa_driver_scan_params params;
    1028             :         struct wpa_driver_scan_params *scan_params;
    1029             :         enum wpa_states prev_state;
    1030         205 :         struct wpa_ssid *ssid = NULL;
    1031         205 :         struct wpabuf *extra_ie = NULL;
    1032             :         int ret;
    1033             :         unsigned int max_sched_scan_ssids;
    1034         205 :         int wildcard = 0;
    1035             :         int need_ssids;
    1036             : 
    1037         205 :         if (!wpa_s->sched_scan_supported)
    1038         205 :                 return -1;
    1039             : 
    1040           0 :         if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
    1041           0 :                 max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
    1042             :         else
    1043           0 :                 max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
    1044           0 :         if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
    1045           0 :                 return -1;
    1046             : 
    1047           0 :         if (wpa_s->sched_scanning) {
    1048           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
    1049           0 :                 return 0;
    1050             :         }
    1051             : 
    1052           0 :         need_ssids = 0;
    1053           0 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    1054           0 :                 if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) {
    1055             :                         /* Use wildcard SSID to find this network */
    1056           0 :                         wildcard = 1;
    1057           0 :                 } else if (!wpas_network_disabled(wpa_s, ssid) &&
    1058           0 :                            ssid->ssid_len)
    1059           0 :                         need_ssids++;
    1060             : 
    1061             : #ifdef CONFIG_WPS
    1062           0 :                 if (!wpas_network_disabled(wpa_s, ssid) &&
    1063           0 :                     ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
    1064             :                         /*
    1065             :                          * Normal scan is more reliable and faster for WPS
    1066             :                          * operations and since these are for short periods of
    1067             :                          * time, the benefit of trying to use sched_scan would
    1068             :                          * be limited.
    1069             :                          */
    1070           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
    1071             :                                 "sched_scan for WPS");
    1072           0 :                         return -1;
    1073             :                 }
    1074             : #endif /* CONFIG_WPS */
    1075             :         }
    1076           0 :         if (wildcard)
    1077           0 :                 need_ssids++;
    1078             : 
    1079           0 :         if (wpa_s->normal_scans < 3 &&
    1080           0 :             (need_ssids <= wpa_s->max_scan_ssids ||
    1081           0 :              wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) {
    1082             :                 /*
    1083             :                  * When normal scan can speed up operations, use that for the
    1084             :                  * first operations before starting the sched_scan to allow
    1085             :                  * user space sleep more. We do this only if the normal scan
    1086             :                  * has functionality that is suitable for this or if the
    1087             :                  * sched_scan does not have better support for multiple SSIDs.
    1088             :                  */
    1089           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
    1090             :                         "sched_scan for initial scans (normal_scans=%d)",
    1091             :                         wpa_s->normal_scans);
    1092           0 :                 return -1;
    1093             :         }
    1094             : 
    1095           0 :         os_memset(&params, 0, sizeof(params));
    1096             : 
    1097             :         /* If we can't allocate space for the filters, we just don't filter */
    1098           0 :         params.filter_ssids = os_zalloc(wpa_s->max_match_sets *
    1099             :                                         sizeof(struct wpa_driver_scan_filter));
    1100             : 
    1101           0 :         prev_state = wpa_s->wpa_state;
    1102           0 :         if (wpa_s->wpa_state == WPA_DISCONNECTED ||
    1103           0 :             wpa_s->wpa_state == WPA_INACTIVE)
    1104           0 :                 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
    1105             : 
    1106           0 :         if (wpa_s->autoscan_params != NULL) {
    1107           0 :                 scan_params = wpa_s->autoscan_params;
    1108           0 :                 goto scan;
    1109             :         }
    1110             : 
    1111             :         /* Find the starting point from which to continue scanning */
    1112           0 :         ssid = wpa_s->conf->ssid;
    1113           0 :         if (wpa_s->prev_sched_ssid) {
    1114           0 :                 while (ssid) {
    1115           0 :                         if (ssid == wpa_s->prev_sched_ssid) {
    1116           0 :                                 ssid = ssid->next;
    1117           0 :                                 break;
    1118             :                         }
    1119           0 :                         ssid = ssid->next;
    1120             :                 }
    1121             :         }
    1122             : 
    1123           0 :         if (!ssid || !wpa_s->prev_sched_ssid) {
    1124           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
    1125           0 :                 if (wpa_s->conf->sched_scan_interval)
    1126           0 :                         wpa_s->sched_scan_interval =
    1127           0 :                                 wpa_s->conf->sched_scan_interval;
    1128           0 :                 if (wpa_s->sched_scan_interval == 0)
    1129           0 :                         wpa_s->sched_scan_interval = 10;
    1130           0 :                 wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
    1131           0 :                 wpa_s->first_sched_scan = 1;
    1132           0 :                 ssid = wpa_s->conf->ssid;
    1133           0 :                 wpa_s->prev_sched_ssid = ssid;
    1134             :         }
    1135             : 
    1136           0 :         if (wildcard) {
    1137           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan");
    1138           0 :                 params.num_ssids++;
    1139             :         }
    1140             : 
    1141           0 :         while (ssid) {
    1142           0 :                 if (wpas_network_disabled(wpa_s, ssid))
    1143           0 :                         goto next;
    1144             : 
    1145           0 :                 if (params.num_filter_ssids < wpa_s->max_match_sets &&
    1146           0 :                     params.filter_ssids && ssid->ssid && ssid->ssid_len) {
    1147           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s",
    1148             :                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
    1149           0 :                         os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid,
    1150             :                                   ssid->ssid, ssid->ssid_len);
    1151           0 :                         params.filter_ssids[params.num_filter_ssids].ssid_len =
    1152           0 :                                 ssid->ssid_len;
    1153           0 :                         params.num_filter_ssids++;
    1154           0 :                 } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len)
    1155             :                 {
    1156           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID "
    1157             :                                 "filter for sched_scan - drop filter");
    1158           0 :                         os_free(params.filter_ssids);
    1159           0 :                         params.filter_ssids = NULL;
    1160           0 :                         params.num_filter_ssids = 0;
    1161             :                 }
    1162             : 
    1163           0 :                 if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) {
    1164           0 :                         if (params.num_ssids == max_sched_scan_ssids)
    1165           0 :                                 break; /* only room for broadcast SSID */
    1166           0 :                         wpa_dbg(wpa_s, MSG_DEBUG,
    1167             :                                 "add to active scan ssid: %s",
    1168             :                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
    1169           0 :                         params.ssids[params.num_ssids].ssid =
    1170           0 :                                 ssid->ssid;
    1171           0 :                         params.ssids[params.num_ssids].ssid_len =
    1172           0 :                                 ssid->ssid_len;
    1173           0 :                         params.num_ssids++;
    1174           0 :                         if (params.num_ssids >= max_sched_scan_ssids) {
    1175           0 :                                 wpa_s->prev_sched_ssid = ssid;
    1176             :                                 do {
    1177           0 :                                         ssid = ssid->next;
    1178           0 :                                 } while (ssid &&
    1179           0 :                                          (wpas_network_disabled(wpa_s, ssid) ||
    1180           0 :                                           !ssid->scan_ssid));
    1181           0 :                                 break;
    1182             :                         }
    1183             :                 }
    1184             : 
    1185             :         next:
    1186           0 :                 wpa_s->prev_sched_ssid = ssid;
    1187           0 :                 ssid = ssid->next;
    1188             :         }
    1189             : 
    1190           0 :         if (params.num_filter_ssids == 0) {
    1191           0 :                 os_free(params.filter_ssids);
    1192           0 :                 params.filter_ssids = NULL;
    1193             :         }
    1194             : 
    1195           0 :         extra_ie = wpa_supplicant_extra_ies(wpa_s);
    1196           0 :         if (extra_ie) {
    1197           0 :                 params.extra_ies = wpabuf_head(extra_ie);
    1198           0 :                 params.extra_ies_len = wpabuf_len(extra_ie);
    1199             :         }
    1200             : 
    1201           0 :         if (wpa_s->conf->filter_rssi)
    1202           0 :                 params.filter_rssi = wpa_s->conf->filter_rssi;
    1203             : 
    1204           0 :         scan_params = &params;
    1205             : 
    1206             : scan:
    1207           0 :         if (ssid || !wpa_s->first_sched_scan) {
    1208           0 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    1209             :                         "Starting sched scan: interval %d timeout %d",
    1210             :                         wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout);
    1211             :         } else {
    1212           0 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    1213             :                         "Starting sched scan: interval %d (no timeout)",
    1214             :                         wpa_s->sched_scan_interval);
    1215             :         }
    1216             : 
    1217           0 :         wpa_setband_scan_freqs(wpa_s, scan_params);
    1218             : 
    1219           0 :         ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
    1220             :                                               wpa_s->sched_scan_interval);
    1221           0 :         wpabuf_free(extra_ie);
    1222           0 :         os_free(params.filter_ssids);
    1223           0 :         if (ret) {
    1224           0 :                 wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan");
    1225           0 :                 if (prev_state != wpa_s->wpa_state)
    1226           0 :                         wpa_supplicant_set_state(wpa_s, prev_state);
    1227           0 :                 return ret;
    1228             :         }
    1229             : 
    1230             :         /* If we have more SSIDs to scan, add a timeout so we scan them too */
    1231           0 :         if (ssid || !wpa_s->first_sched_scan) {
    1232           0 :                 wpa_s->sched_scan_timed_out = 0;
    1233           0 :                 eloop_register_timeout(wpa_s->sched_scan_timeout, 0,
    1234             :                                        wpa_supplicant_sched_scan_timeout,
    1235             :                                        wpa_s, NULL);
    1236           0 :                 wpa_s->first_sched_scan = 0;
    1237           0 :                 wpa_s->sched_scan_timeout /= 2;
    1238           0 :                 wpa_s->sched_scan_interval *= 2;
    1239           0 :                 if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) {
    1240           0 :                         wpa_s->sched_scan_interval = 10;
    1241           0 :                         wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
    1242             :                 }
    1243             :         }
    1244             : 
    1245             :         /* If there is no more ssids, start next time from the beginning */
    1246           0 :         if (!ssid)
    1247           0 :                 wpa_s->prev_sched_ssid = NULL;
    1248             : 
    1249           0 :         return 0;
    1250             : }
    1251             : 
    1252             : 
    1253             : /**
    1254             :  * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
    1255             :  * @wpa_s: Pointer to wpa_supplicant data
    1256             :  *
    1257             :  * This function is used to cancel a scan request scheduled with
    1258             :  * wpa_supplicant_req_scan().
    1259             :  */
    1260        3122 : void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
    1261             : {
    1262        3122 :         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
    1263        3122 :         eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
    1264        3122 : }
    1265             : 
    1266             : 
    1267             : /**
    1268             :  * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan
    1269             :  * @wpa_s: Pointer to wpa_supplicant data
    1270             :  *
    1271             :  * This function is used to stop a delayed scheduled scan.
    1272             :  */
    1273          78 : void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s)
    1274             : {
    1275          78 :         if (!wpa_s->sched_scan_supported)
    1276         156 :                 return;
    1277             : 
    1278           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan");
    1279           0 :         eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout,
    1280             :                              wpa_s, NULL);
    1281             : }
    1282             : 
    1283             : 
    1284             : /**
    1285             :  * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans
    1286             :  * @wpa_s: Pointer to wpa_supplicant data
    1287             :  *
    1288             :  * This function is used to stop a periodic scheduled scan.
    1289             :  */
    1290        2263 : void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
    1291             : {
    1292        2263 :         if (!wpa_s->sched_scanning)
    1293        4526 :                 return;
    1294             : 
    1295           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
    1296           0 :         eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
    1297           0 :         wpa_supplicant_stop_sched_scan(wpa_s);
    1298             : }
    1299             : 
    1300             : 
    1301             : /**
    1302             :  * wpa_supplicant_notify_scanning - Indicate possible scan state change
    1303             :  * @wpa_s: Pointer to wpa_supplicant data
    1304             :  * @scanning: Whether scanning is currently in progress
    1305             :  *
    1306             :  * This function is to generate scanning notifycations. It is called whenever
    1307             :  * there may have been a change in scanning (scan started, completed, stopped).
    1308             :  * wpas_notify_scanning() is called whenever the scanning state changed from the
    1309             :  * previously notified state.
    1310             :  */
    1311       12240 : void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
    1312             :                                     int scanning)
    1313             : {
    1314       12240 :         if (wpa_s->scanning != scanning) {
    1315        2394 :                 wpa_s->scanning = scanning;
    1316        2394 :                 wpas_notify_scanning(wpa_s);
    1317             :         }
    1318       12240 : }
    1319             : 
    1320             : 
    1321         876 : static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
    1322             : {
    1323         876 :         int rate = 0;
    1324             :         const u8 *ie;
    1325             :         int i;
    1326             : 
    1327         876 :         ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
    1328        7884 :         for (i = 0; ie && i < ie[1]; i++) {
    1329        7008 :                 if ((ie[i + 2] & 0x7f) > rate)
    1330        6076 :                         rate = ie[i + 2] & 0x7f;
    1331             :         }
    1332             : 
    1333         876 :         ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
    1334        2740 :         for (i = 0; ie && i < ie[1]; i++) {
    1335        1864 :                 if ((ie[i + 2] & 0x7f) > rate)
    1336        1864 :                         rate = ie[i + 2] & 0x7f;
    1337             :         }
    1338             : 
    1339         876 :         return rate;
    1340             : }
    1341             : 
    1342             : 
    1343             : /**
    1344             :  * wpa_scan_get_ie - Fetch a specified information element from a scan result
    1345             :  * @res: Scan result entry
    1346             :  * @ie: Information element identitifier (WLAN_EID_*)
    1347             :  * Returns: Pointer to the information element (id field) or %NULL if not found
    1348             :  *
    1349             :  * This function returns the first matching information element in the scan
    1350             :  * result.
    1351             :  */
    1352        5962 : const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
    1353             : {
    1354             :         const u8 *end, *pos;
    1355             : 
    1356        5962 :         pos = (const u8 *) (res + 1);
    1357        5962 :         end = pos + res->ie_len;
    1358             : 
    1359       29448 :         while (pos + 1 < end) {
    1360       22003 :                 if (pos + 2 + pos[1] > end)
    1361           0 :                         break;
    1362       22003 :                 if (pos[0] == ie)
    1363        4479 :                         return pos;
    1364       17524 :                 pos += 2 + pos[1];
    1365             :         }
    1366             : 
    1367        1483 :         return NULL;
    1368             : }
    1369             : 
    1370             : 
    1371             : /**
    1372             :  * wpa_scan_get_vendor_ie - Fetch vendor information element from a scan result
    1373             :  * @res: Scan result entry
    1374             :  * @vendor_type: Vendor type (four octets starting the IE payload)
    1375             :  * Returns: Pointer to the information element (id field) or %NULL if not found
    1376             :  *
    1377             :  * This function returns the first matching information element in the scan
    1378             :  * result.
    1379             :  */
    1380        6383 : const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
    1381             :                                   u32 vendor_type)
    1382             : {
    1383             :         const u8 *end, *pos;
    1384             : 
    1385        6383 :         pos = (const u8 *) (res + 1);
    1386        6383 :         end = pos + res->ie_len;
    1387             : 
    1388       70687 :         while (pos + 1 < end) {
    1389       60005 :                 if (pos + 2 + pos[1] > end)
    1390           0 :                         break;
    1391       72072 :                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    1392       12067 :                     vendor_type == WPA_GET_BE32(&pos[2]))
    1393        2084 :                         return pos;
    1394       57921 :                 pos += 2 + pos[1];
    1395             :         }
    1396             : 
    1397        4299 :         return NULL;
    1398             : }
    1399             : 
    1400             : 
    1401             : /**
    1402             :  * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result
    1403             :  * @res: Scan result entry
    1404             :  * @vendor_type: Vendor type (four octets starting the IE payload)
    1405             :  * Returns: Pointer to the information element (id field) or %NULL if not found
    1406             :  *
    1407             :  * This function returns the first matching information element in the scan
    1408             :  * result.
    1409             :  *
    1410             :  * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only
    1411             :  * from Beacon frames instead of either Beacon or Probe Response frames.
    1412             :  */
    1413         255 : const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
    1414             :                                          u32 vendor_type)
    1415             : {
    1416             :         const u8 *end, *pos;
    1417             : 
    1418         255 :         if (res->beacon_ie_len == 0)
    1419           0 :                 return NULL;
    1420             : 
    1421         255 :         pos = (const u8 *) (res + 1);
    1422         255 :         pos += res->ie_len;
    1423         255 :         end = pos + res->beacon_ie_len;
    1424             : 
    1425        3154 :         while (pos + 1 < end) {
    1426        2660 :                 if (pos + 2 + pos[1] > end)
    1427           0 :                         break;
    1428        3021 :                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    1429         361 :                     vendor_type == WPA_GET_BE32(&pos[2]))
    1430          16 :                         return pos;
    1431        2644 :                 pos += 2 + pos[1];
    1432             :         }
    1433             : 
    1434         239 :         return NULL;
    1435             : }
    1436             : 
    1437             : 
    1438             : /**
    1439             :  * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result
    1440             :  * @res: Scan result entry
    1441             :  * @vendor_type: Vendor type (four octets starting the IE payload)
    1442             :  * Returns: Pointer to the information element payload or %NULL if not found
    1443             :  *
    1444             :  * This function returns concatenated payload of possibly fragmented vendor
    1445             :  * specific information elements in the scan result. The caller is responsible
    1446             :  * for freeing the returned buffer.
    1447             :  */
    1448         557 : struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
    1449             :                                              u32 vendor_type)
    1450             : {
    1451             :         struct wpabuf *buf;
    1452             :         const u8 *end, *pos;
    1453             : 
    1454         557 :         buf = wpabuf_alloc(res->ie_len);
    1455         557 :         if (buf == NULL)
    1456           0 :                 return NULL;
    1457             : 
    1458         557 :         pos = (const u8 *) (res + 1);
    1459         557 :         end = pos + res->ie_len;
    1460             : 
    1461        6874 :         while (pos + 1 < end) {
    1462        5760 :                 if (pos + 2 + pos[1] > end)
    1463           0 :                         break;
    1464        7125 :                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    1465        1365 :                     vendor_type == WPA_GET_BE32(&pos[2]))
    1466         543 :                         wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
    1467        5760 :                 pos += 2 + pos[1];
    1468             :         }
    1469             : 
    1470         557 :         if (wpabuf_len(buf) == 0) {
    1471          15 :                 wpabuf_free(buf);
    1472          15 :                 buf = NULL;
    1473             :         }
    1474             : 
    1475         557 :         return buf;
    1476             : }
    1477             : 
    1478             : 
    1479             : /*
    1480             :  * Channels with a great SNR can operate at full rate. What is a great SNR?
    1481             :  * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
    1482             :  * rule of thumb is that any SNR above 20 is good." This one
    1483             :  * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
    1484             :  * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
    1485             :  * conservative value.
    1486             :  */
    1487             : #define GREAT_SNR 30
    1488             : 
    1489             : /* Compare function for sorting scan results. Return >0 if @b is considered
    1490             :  * better. */
    1491         994 : static int wpa_scan_result_compar(const void *a, const void *b)
    1492             : {
    1493             : #define IS_5GHZ(n) (n > 4000)
    1494             : #define MIN(a,b) a < b ? a : b
    1495         994 :         struct wpa_scan_res **_wa = (void *) a;
    1496         994 :         struct wpa_scan_res **_wb = (void *) b;
    1497         994 :         struct wpa_scan_res *wa = *_wa;
    1498         994 :         struct wpa_scan_res *wb = *_wb;
    1499             :         int wpa_a, wpa_b, maxrate_a, maxrate_b;
    1500             :         int snr_a, snr_b;
    1501             : 
    1502             :         /* WPA/WPA2 support preferred */
    1503        1936 :         wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
    1504         942 :                 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
    1505        1964 :         wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
    1506         970 :                 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
    1507             : 
    1508         994 :         if (wpa_b && !wpa_a)
    1509          80 :                 return 1;
    1510         914 :         if (!wpa_b && wpa_a)
    1511         406 :                 return -1;
    1512             : 
    1513             :         /* privacy support preferred */
    1514         684 :         if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
    1515         176 :             (wb->caps & IEEE80211_CAP_PRIVACY))
    1516          56 :                 return 1;
    1517         784 :         if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
    1518         332 :             (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
    1519          14 :                 return -1;
    1520             : 
    1521         876 :         if ((wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) &&
    1522         438 :             !((wa->flags | wb->flags) & WPA_SCAN_NOISE_INVALID)) {
    1523         276 :                 snr_a = MIN(wa->level - wa->noise, GREAT_SNR);
    1524         276 :                 snr_b = MIN(wb->level - wb->noise, GREAT_SNR);
    1525             :         } else {
    1526             :                 /* Not suitable information to calculate SNR, so use level */
    1527         162 :                 snr_a = wa->level;
    1528         162 :                 snr_b = wb->level;
    1529             :         }
    1530             : 
    1531             :         /* best/max rate preferred if SNR close enough */
    1532         438 :         if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
    1533           0 :             (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
    1534         438 :                 maxrate_a = wpa_scan_get_max_rate(wa);
    1535         438 :                 maxrate_b = wpa_scan_get_max_rate(wb);
    1536         438 :                 if (maxrate_a != maxrate_b)
    1537           0 :                         return maxrate_b - maxrate_a;
    1538         438 :                 if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
    1539           2 :                         return IS_5GHZ(wa->freq) ? -1 : 1;
    1540             :         }
    1541             : 
    1542             :         /* use freq for channel preference */
    1543             : 
    1544             :         /* all things being equal, use SNR; if SNRs are
    1545             :          * identical, use quality values since some drivers may only report
    1546             :          * that value and leave the signal level zero */
    1547         436 :         if (snr_b == snr_a)
    1548         436 :                 return wb->qual - wa->qual;
    1549           0 :         return snr_b - snr_a;
    1550             : #undef MIN
    1551             : #undef IS_5GHZ
    1552             : }
    1553             : 
    1554             : 
    1555             : #ifdef CONFIG_WPS
    1556             : /* Compare function for sorting scan results when searching a WPS AP for
    1557             :  * provisioning. Return >0 if @b is considered better. */
    1558          64 : static int wpa_scan_result_wps_compar(const void *a, const void *b)
    1559             : {
    1560          64 :         struct wpa_scan_res **_wa = (void *) a;
    1561          64 :         struct wpa_scan_res **_wb = (void *) b;
    1562          64 :         struct wpa_scan_res *wa = *_wa;
    1563          64 :         struct wpa_scan_res *wb = *_wb;
    1564             :         int uses_wps_a, uses_wps_b;
    1565             :         struct wpabuf *wps_a, *wps_b;
    1566             :         int res;
    1567             : 
    1568             :         /* Optimization - check WPS IE existence before allocated memory and
    1569             :          * doing full reassembly. */
    1570          64 :         uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
    1571          64 :         uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
    1572          64 :         if (uses_wps_a && !uses_wps_b)
    1573           0 :                 return -1;
    1574          64 :         if (!uses_wps_a && uses_wps_b)
    1575          13 :                 return 1;
    1576             : 
    1577          51 :         if (uses_wps_a && uses_wps_b) {
    1578          51 :                 wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
    1579          51 :                 wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
    1580          51 :                 res = wps_ap_priority_compar(wps_a, wps_b);
    1581          51 :                 wpabuf_free(wps_a);
    1582          51 :                 wpabuf_free(wps_b);
    1583          51 :                 if (res)
    1584          26 :                         return res;
    1585             :         }
    1586             : 
    1587             :         /*
    1588             :          * Do not use current AP security policy as a sorting criteria during
    1589             :          * WPS provisioning step since the AP may get reconfigured at the
    1590             :          * completion of provisioning.
    1591             :          */
    1592             : 
    1593             :         /* all things being equal, use signal level; if signal levels are
    1594             :          * identical, use quality values since some drivers may only report
    1595             :          * that value and leave the signal level zero */
    1596          25 :         if (wb->level == wa->level)
    1597          24 :                 return wb->qual - wa->qual;
    1598           1 :         return wb->level - wa->level;
    1599             : }
    1600             : #endif /* CONFIG_WPS */
    1601             : 
    1602             : 
    1603        1855 : static void dump_scan_res(struct wpa_scan_results *scan_res)
    1604             : {
    1605             : #ifndef CONFIG_NO_STDOUT_DEBUG
    1606             :         size_t i;
    1607             : 
    1608        1855 :         if (scan_res->res == NULL || scan_res->num == 0)
    1609        1942 :                 return;
    1610             : 
    1611        1768 :         wpa_printf(MSG_EXCESSIVE, "Sorted scan results");
    1612             : 
    1613        4544 :         for (i = 0; i < scan_res->num; i++) {
    1614        2776 :                 struct wpa_scan_res *r = scan_res->res[i];
    1615             :                 u8 *pos;
    1616        2776 :                 if ((r->flags & (WPA_SCAN_LEVEL_DBM | WPA_SCAN_NOISE_INVALID))
    1617             :                     == WPA_SCAN_LEVEL_DBM) {
    1618        1958 :                         int snr = r->level - r->noise;
    1619       13706 :                         wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
    1620             :                                    "noise=%d level=%d snr=%d%s flags=0x%x "
    1621             :                                    "age=%u",
    1622       11748 :                                    MAC2STR(r->bssid), r->freq, r->qual,
    1623             :                                    r->noise, r->level, snr,
    1624             :                                    snr >= GREAT_SNR ? "*" : "", r->flags,
    1625             :                                    r->age);
    1626             :                 } else {
    1627        5726 :                         wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
    1628             :                                    "noise=%d level=%d flags=0x%x age=%u",
    1629        4908 :                                    MAC2STR(r->bssid), r->freq, r->qual,
    1630             :                                    r->noise, r->level, r->flags, r->age);
    1631             :                 }
    1632        2776 :                 pos = (u8 *) (r + 1);
    1633        2776 :                 if (r->ie_len)
    1634        2776 :                         wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len);
    1635        2776 :                 pos += r->ie_len;
    1636        2776 :                 if (r->beacon_ie_len)
    1637        1738 :                         wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs",
    1638             :                                     pos, r->beacon_ie_len);
    1639             :         }
    1640             : #endif /* CONFIG_NO_STDOUT_DEBUG */
    1641             : }
    1642             : 
    1643             : 
    1644             : /**
    1645             :  * wpa_supplicant_filter_bssid_match - Is the specified BSSID allowed
    1646             :  * @wpa_s: Pointer to wpa_supplicant data
    1647             :  * @bssid: BSSID to check
    1648             :  * Returns: 0 if the BSSID is filtered or 1 if not
    1649             :  *
    1650             :  * This function is used to filter out specific BSSIDs from scan reslts mainly
    1651             :  * for testing purposes (SET bssid_filter ctrl_iface command).
    1652             :  */
    1653        2907 : int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
    1654             :                                       const u8 *bssid)
    1655             : {
    1656             :         size_t i;
    1657             : 
    1658        2907 :         if (wpa_s->bssid_filter == NULL)
    1659        2897 :                 return 1;
    1660             : 
    1661          13 :         for (i = 0; i < wpa_s->bssid_filter_count; i++) {
    1662          10 :                 if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
    1663             :                               ETH_ALEN) == 0)
    1664           7 :                         return 1;
    1665             :         }
    1666             : 
    1667           3 :         return 0;
    1668             : }
    1669             : 
    1670             : 
    1671        1855 : static void filter_scan_res(struct wpa_supplicant *wpa_s,
    1672             :                             struct wpa_scan_results *res)
    1673             : {
    1674             :         size_t i, j;
    1675             : 
    1676        1855 :         if (wpa_s->bssid_filter == NULL)
    1677        3708 :                 return;
    1678             : 
    1679           6 :         for (i = 0, j = 0; i < res->num; i++) {
    1680           4 :                 if (wpa_supplicant_filter_bssid_match(wpa_s,
    1681           4 :                                                       res->res[i]->bssid)) {
    1682           2 :                         res->res[j++] = res->res[i];
    1683             :                 } else {
    1684           2 :                         os_free(res->res[i]);
    1685           2 :                         res->res[i] = NULL;
    1686             :                 }
    1687             :         }
    1688             : 
    1689           2 :         if (res->num != j) {
    1690           2 :                 wpa_printf(MSG_DEBUG, "Filtered out %d scan results",
    1691           2 :                            (int) (res->num - j));
    1692           2 :                 res->num = j;
    1693             :         }
    1694             : }
    1695             : 
    1696             : 
    1697             : /**
    1698             :  * wpa_supplicant_get_scan_results - Get scan results
    1699             :  * @wpa_s: Pointer to wpa_supplicant data
    1700             :  * @info: Information about what was scanned or %NULL if not available
    1701             :  * @new_scan: Whether a new scan was performed
    1702             :  * Returns: Scan results, %NULL on failure
    1703             :  *
    1704             :  * This function request the current scan results from the driver and updates
    1705             :  * the local BSS list wpa_s->bss. The caller is responsible for freeing the
    1706             :  * results with wpa_scan_results_free().
    1707             :  */
    1708             : struct wpa_scan_results *
    1709        1855 : wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
    1710             :                                 struct scan_info *info, int new_scan)
    1711             : {
    1712             :         struct wpa_scan_results *scan_res;
    1713             :         size_t i;
    1714        1855 :         int (*compar)(const void *, const void *) = wpa_scan_result_compar;
    1715             : 
    1716        1855 :         scan_res = wpa_drv_get_scan_results2(wpa_s);
    1717        1855 :         if (scan_res == NULL) {
    1718           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
    1719           0 :                 return NULL;
    1720             :         }
    1721        1855 :         if (scan_res->fetch_time.sec == 0) {
    1722             :                 /*
    1723             :                  * Make sure we have a valid timestamp if the driver wrapper
    1724             :                  * does not set this.
    1725             :                  */
    1726        1855 :                 os_get_reltime(&scan_res->fetch_time);
    1727             :         }
    1728        1855 :         filter_scan_res(wpa_s, scan_res);
    1729             : 
    1730             : #ifdef CONFIG_WPS
    1731        1855 :         if (wpas_wps_searching(wpa_s)) {
    1732         305 :                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
    1733             :                         "provisioning rules");
    1734         305 :                 compar = wpa_scan_result_wps_compar;
    1735             :         }
    1736             : #endif /* CONFIG_WPS */
    1737             : 
    1738        1855 :         qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
    1739             :               compar);
    1740        1855 :         dump_scan_res(scan_res);
    1741             : 
    1742        1855 :         wpa_bss_update_start(wpa_s);
    1743        4631 :         for (i = 0; i < scan_res->num; i++)
    1744        2776 :                 wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
    1745             :                                         &scan_res->fetch_time);
    1746        1855 :         wpa_bss_update_end(wpa_s, info, new_scan);
    1747             : 
    1748        1855 :         return scan_res;
    1749             : }
    1750             : 
    1751             : 
    1752             : /**
    1753             :  * wpa_supplicant_update_scan_results - Update scan results from the driver
    1754             :  * @wpa_s: Pointer to wpa_supplicant data
    1755             :  * Returns: 0 on success, -1 on failure
    1756             :  *
    1757             :  * This function updates the BSS table within wpa_supplicant based on the
    1758             :  * currently available scan results from the driver without requesting a new
    1759             :  * scan. This is used in cases where the driver indicates an association
    1760             :  * (including roaming within ESS) and wpa_supplicant does not yet have the
    1761             :  * needed information to complete the connection (e.g., to perform validation
    1762             :  * steps in 4-way handshake).
    1763             :  */
    1764           2 : int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
    1765             : {
    1766             :         struct wpa_scan_results *scan_res;
    1767           2 :         scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
    1768           2 :         if (scan_res == NULL)
    1769           0 :                 return -1;
    1770           2 :         wpa_scan_results_free(scan_res);
    1771             : 
    1772           2 :         return 0;
    1773             : }
    1774             : 
    1775             : 
    1776             : /**
    1777             :  * scan_only_handler - Reports scan results
    1778             :  */
    1779           5 : void scan_only_handler(struct wpa_supplicant *wpa_s,
    1780             :                        struct wpa_scan_results *scan_res)
    1781             : {
    1782           5 :         wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received");
    1783           5 :         if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
    1784           3 :             wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
    1785           3 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
    1786             :                              wpa_s->manual_scan_id);
    1787           3 :                 wpa_s->manual_scan_use_id = 0;
    1788             :         } else {
    1789           2 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
    1790             :         }
    1791           5 :         wpas_notify_scan_results(wpa_s);
    1792           5 :         wpas_notify_scan_done(wpa_s, 1);
    1793           5 :         if (wpa_s->scan_work) {
    1794           5 :                 struct wpa_radio_work *work = wpa_s->scan_work;
    1795           5 :                 wpa_s->scan_work = NULL;
    1796           5 :                 radio_work_done(work);
    1797             :         }
    1798           5 : }
    1799             : 
    1800             : 
    1801           0 : int wpas_scan_scheduled(struct wpa_supplicant *wpa_s)
    1802             : {
    1803           0 :         return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL);
    1804             : }
    1805             : 
    1806             : 
    1807             : struct wpa_driver_scan_params *
    1808        1197 : wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
    1809             : {
    1810             :         struct wpa_driver_scan_params *params;
    1811             :         size_t i;
    1812             :         u8 *n;
    1813             : 
    1814        1197 :         params = os_zalloc(sizeof(*params));
    1815        1197 :         if (params == NULL)
    1816           0 :                 return NULL;
    1817             : 
    1818        2385 :         for (i = 0; i < src->num_ssids; i++) {
    1819        1188 :                 if (src->ssids[i].ssid) {
    1820         168 :                         n = os_malloc(src->ssids[i].ssid_len);
    1821         168 :                         if (n == NULL)
    1822           0 :                                 goto failed;
    1823         168 :                         os_memcpy(n, src->ssids[i].ssid,
    1824             :                                   src->ssids[i].ssid_len);
    1825         168 :                         params->ssids[i].ssid = n;
    1826         168 :                         params->ssids[i].ssid_len = src->ssids[i].ssid_len;
    1827             :                 }
    1828             :         }
    1829        1197 :         params->num_ssids = src->num_ssids;
    1830             : 
    1831        1197 :         if (src->extra_ies) {
    1832        1184 :                 n = os_malloc(src->extra_ies_len);
    1833        1184 :                 if (n == NULL)
    1834           0 :                         goto failed;
    1835        1184 :                 os_memcpy(n, src->extra_ies, src->extra_ies_len);
    1836        1184 :                 params->extra_ies = n;
    1837        1184 :                 params->extra_ies_len = src->extra_ies_len;
    1838             :         }
    1839             : 
    1840        1197 :         if (src->freqs) {
    1841        1021 :                 int len = int_array_len(src->freqs);
    1842        1021 :                 params->freqs = os_malloc((len + 1) * sizeof(int));
    1843        1021 :                 if (params->freqs == NULL)
    1844           0 :                         goto failed;
    1845        1021 :                 os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int));
    1846             :         }
    1847             : 
    1848        1197 :         if (src->filter_ssids) {
    1849           1 :                 params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) *
    1850           1 :                                                  src->num_filter_ssids);
    1851           1 :                 if (params->filter_ssids == NULL)
    1852           0 :                         goto failed;
    1853           1 :                 os_memcpy(params->filter_ssids, src->filter_ssids,
    1854             :                           sizeof(*params->filter_ssids) *
    1855             :                           src->num_filter_ssids);
    1856           1 :                 params->num_filter_ssids = src->num_filter_ssids;
    1857             :         }
    1858             : 
    1859        1197 :         params->filter_rssi = src->filter_rssi;
    1860        1197 :         params->p2p_probe = src->p2p_probe;
    1861        1197 :         params->only_new_results = src->only_new_results;
    1862             : 
    1863        1197 :         return params;
    1864             : 
    1865             : failed:
    1866           0 :         wpa_scan_free_params(params);
    1867           0 :         return NULL;
    1868             : }
    1869             : 
    1870             : 
    1871        1811 : void wpa_scan_free_params(struct wpa_driver_scan_params *params)
    1872             : {
    1873             :         size_t i;
    1874             : 
    1875        1811 :         if (params == NULL)
    1876        1811 :                 return;
    1877             : 
    1878        3613 :         for (i = 0; i < params->num_ssids; i++)
    1879        1802 :                 os_free((u8 *) params->ssids[i].ssid);
    1880        1811 :         os_free((u8 *) params->extra_ies);
    1881        1811 :         os_free(params->freqs);
    1882        1811 :         os_free(params->filter_ssids);
    1883        1811 :         os_free(params);
    1884             : }
    1885             : 
    1886             : 
    1887           4 : int wpas_start_pno(struct wpa_supplicant *wpa_s)
    1888             : {
    1889             :         int ret, interval;
    1890             :         size_t i, num_ssid;
    1891             :         struct wpa_ssid *ssid;
    1892             :         struct wpa_driver_scan_params params;
    1893             : 
    1894           4 :         if (!wpa_s->sched_scan_supported)
    1895           4 :                 return -1;
    1896             : 
    1897           0 :         if (wpa_s->pno || wpa_s->pno_sched_pending)
    1898           0 :                 return 0;
    1899             : 
    1900           0 :         if ((wpa_s->wpa_state > WPA_SCANNING) &&
    1901           0 :             (wpa_s->wpa_state <= WPA_COMPLETED)) {
    1902           0 :                 wpa_printf(MSG_ERROR, "PNO: In assoc process");
    1903           0 :                 return -EAGAIN;
    1904             :         }
    1905             : 
    1906           0 :         if (wpa_s->wpa_state == WPA_SCANNING) {
    1907           0 :                 wpa_supplicant_cancel_scan(wpa_s);
    1908           0 :                 if (wpa_s->sched_scanning) {
    1909           0 :                         wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
    1910             :                                    "ongoing sched scan");
    1911           0 :                         wpa_supplicant_cancel_sched_scan(wpa_s);
    1912           0 :                         wpa_s->pno_sched_pending = 1;
    1913           0 :                         return 0;
    1914             :                 }
    1915             :         }
    1916             : 
    1917           0 :         os_memset(&params, 0, sizeof(params));
    1918             : 
    1919           0 :         num_ssid = 0;
    1920           0 :         ssid = wpa_s->conf->ssid;
    1921           0 :         while (ssid) {
    1922           0 :                 if (!wpas_network_disabled(wpa_s, ssid))
    1923           0 :                         num_ssid++;
    1924           0 :                 ssid = ssid->next;
    1925             :         }
    1926           0 :         if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
    1927           0 :                 wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
    1928             :                            "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
    1929           0 :                 num_ssid = WPAS_MAX_SCAN_SSIDS;
    1930             :         }
    1931             : 
    1932           0 :         if (num_ssid == 0) {
    1933           0 :                 wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
    1934           0 :                 return -1;
    1935             :         }
    1936             : 
    1937           0 :         params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
    1938             :                                         num_ssid);
    1939           0 :         if (params.filter_ssids == NULL)
    1940           0 :                 return -1;
    1941           0 :         i = 0;
    1942           0 :         ssid = wpa_s->conf->ssid;
    1943           0 :         while (ssid) {
    1944           0 :                 if (!wpas_network_disabled(wpa_s, ssid)) {
    1945           0 :                         params.ssids[i].ssid = ssid->ssid;
    1946           0 :                         params.ssids[i].ssid_len = ssid->ssid_len;
    1947           0 :                         params.num_ssids++;
    1948           0 :                         os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
    1949             :                                   ssid->ssid_len);
    1950           0 :                         params.filter_ssids[i].ssid_len = ssid->ssid_len;
    1951           0 :                         params.num_filter_ssids++;
    1952           0 :                         i++;
    1953           0 :                         if (i == num_ssid)
    1954           0 :                                 break;
    1955             :                 }
    1956           0 :                 ssid = ssid->next;
    1957             :         }
    1958             : 
    1959           0 :         if (wpa_s->conf->filter_rssi)
    1960           0 :                 params.filter_rssi = wpa_s->conf->filter_rssi;
    1961             : 
    1962           0 :         interval = wpa_s->conf->sched_scan_interval ?
    1963           0 :                 wpa_s->conf->sched_scan_interval : 10;
    1964             : 
    1965           0 :         if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
    1966           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
    1967           0 :                 params.freqs = wpa_s->manual_sched_scan_freqs;
    1968             :         }
    1969             : 
    1970           0 :         ret = wpa_supplicant_start_sched_scan(wpa_s, &params, interval);
    1971           0 :         os_free(params.filter_ssids);
    1972           0 :         if (ret == 0)
    1973           0 :                 wpa_s->pno = 1;
    1974             :         else
    1975           0 :                 wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
    1976           0 :         return ret;
    1977             : }
    1978             : 
    1979             : 
    1980           1 : int wpas_stop_pno(struct wpa_supplicant *wpa_s)
    1981             : {
    1982           1 :         int ret = 0;
    1983             : 
    1984           1 :         if (!wpa_s->pno)
    1985           1 :                 return 0;
    1986             : 
    1987           0 :         ret = wpa_supplicant_stop_sched_scan(wpa_s);
    1988             : 
    1989           0 :         wpa_s->pno = 0;
    1990           0 :         wpa_s->pno_sched_pending = 0;
    1991             : 
    1992           0 :         if (wpa_s->wpa_state == WPA_SCANNING)
    1993           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    1994             : 
    1995           0 :         return ret;
    1996             : }

Generated by: LCOV version 1.10