LCOV - code coverage report
Current view: top level - wpa_supplicant - scan.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1388338050 Lines: 443 795 55.7 %
Date: 2013-12-29 Functions: 29 40 72.5 %
Branches: 303 632 47.9 %

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

Generated by: LCOV version 1.9