LCOV - code coverage report
Current view: top level - wpa_supplicant - scan.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388943092 Lines: 493 854 57.7 %
Date: 2014-01-05 Functions: 32 43 74.4 %
Branches: 324 660 49.1 %

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

Generated by: LCOV version 1.9