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 1393793999 Lines: 511 866 59.0 %
Date: 2014-03-02 Functions: 32 43 74.4 %
Branches: 333 668 49.9 %

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

Generated by: LCOV version 1.9