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 1443382998 Lines: 854 1249 68.4 %
Date: 2015-09-27 Functions: 48 54 88.9 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant - Scanning
       3             :  * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #include "utils/common.h"
      12             : #include "utils/eloop.h"
      13             : #include "common/ieee802_11_defs.h"
      14             : #include "common/wpa_ctrl.h"
      15             : #include "config.h"
      16             : #include "wpa_supplicant_i.h"
      17             : #include "driver_i.h"
      18             : #include "wps_supplicant.h"
      19             : #include "p2p_supplicant.h"
      20             : #include "p2p/p2p.h"
      21             : #include "hs20_supplicant.h"
      22             : #include "notify.h"
      23             : #include "bss.h"
      24             : #include "scan.h"
      25             : #include "mesh.h"
      26             : 
      27             : 
      28           2 : 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           2 :         ssid = wpa_supplicant_get_ssid(wpa_s);
      34           2 :         if (ssid == NULL)
      35           3 :                 return;
      36             : 
      37           1 :         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           1 :         wpa_supplicant_initiate_eapol(wpa_s);
      43           1 :         wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
      44             :                 "network - generating associated event");
      45           1 :         os_memset(&data, 0, sizeof(data));
      46           1 :         wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
      47             : }
      48             : 
      49             : 
      50             : #ifdef CONFIG_WPS
      51        3703 : 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        3703 :         int wps = 0;
      56             : 
      57        5704 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
      58        2150 :                 if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
      59        1529 :                         continue;
      60             : 
      61         621 :                 wps = 1;
      62         621 :                 *req_type = wpas_wps_get_req_type(ssid);
      63         621 :                 if (!ssid->eap.phase1)
      64           0 :                         continue;
      65             : 
      66         621 :                 if (os_strstr(ssid->eap.phase1, "pbc=1"))
      67         149 :                         return 2;
      68             :         }
      69             : 
      70             : #ifdef CONFIG_P2P
      71        7089 :         if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p &&
      72        3535 :             !wpa_s->conf->p2p_disabled) {
      73        3535 :                 wpa_s->wps->dev.p2p = 1;
      74        3535 :                 if (!wps) {
      75        3065 :                         wps = 1;
      76        3065 :                         *req_type = WPS_REQ_ENROLLEE_INFO;
      77             :                 }
      78             :         }
      79             : #endif /* CONFIG_P2P */
      80             : 
      81        3554 :         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        6465 : int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
      96             : {
      97        6465 :         struct wpa_ssid *ssid = wpa_s->conf->ssid;
      98        6465 :         int count = 0, disabled = 0;
      99             : 
     100        6465 :         if (wpa_s->p2p_mgmt)
     101           8 :                 return 0; /* no normal network profiles on p2p_mgmt interface */
     102             : 
     103       16155 :         while (ssid) {
     104        3241 :                 if (!wpas_network_disabled(wpa_s, ssid))
     105        2986 :                         count++;
     106             :                 else
     107         255 :                         disabled++;
     108        3241 :                 ssid = ssid->next;
     109             :         }
     110        6709 :         if (wpa_s->conf->cred && wpa_s->conf->interworking &&
     111         252 :             wpa_s->conf->auto_interworking)
     112          32 :                 count++;
     113        6457 :         if (count == 0 && disabled > 0) {
     114          32 :                 wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled "
     115             :                         "networks)", disabled);
     116             :         }
     117        6457 :         return count;
     118             : }
     119             : 
     120             : 
     121          15 : static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
     122             :                                      struct wpa_ssid *ssid)
     123             : {
     124          33 :         while (ssid) {
     125          17 :                 if (!wpas_network_disabled(wpa_s, ssid))
     126          14 :                         break;
     127           3 :                 ssid = ssid->next;
     128             :         }
     129             : 
     130             :         /* ap_scan=2 mode - try to associate with each SSID. */
     131          15 :         if (ssid == NULL) {
     132           1 :                 wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached "
     133             :                         "end of scan list - go back to beginning");
     134           1 :                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
     135           1 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
     136          16 :                 return;
     137             :         }
     138          14 :         if (ssid->next) {
     139             :                 /* Continue from the next SSID on the next attempt. */
     140           2 :                 wpa_s->prev_scan_ssid = ssid;
     141             :         } else {
     142             :                 /* Start from the beginning of the SSID list. */
     143          12 :                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
     144             :         }
     145          14 :         wpa_supplicant_associate(wpa_s, NULL, ssid);
     146             : }
     147             : 
     148             : 
     149        3729 : static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
     150             : {
     151        3729 :         struct wpa_supplicant *wpa_s = work->wpa_s;
     152        3729 :         struct wpa_driver_scan_params *params = work->ctx;
     153             :         int ret;
     154             : 
     155        3729 :         if (deinit) {
     156          12 :                 if (!work->started) {
     157           0 :                         wpa_scan_free_params(params);
     158           0 :                         return;
     159             :                 }
     160          12 :                 wpa_supplicant_notify_scanning(wpa_s, 0);
     161          12 :                 wpas_notify_scan_done(wpa_s, 0);
     162          12 :                 wpa_s->scan_work = NULL;
     163          12 :                 return;
     164             :         }
     165             : 
     166        3717 :         if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
     167           0 :                 wpa_msg(wpa_s, MSG_INFO,
     168             :                         "Failed to assign random MAC address for a scan");
     169           0 :                 radio_work_done(work);
     170           0 :                 return;
     171             :         }
     172             : 
     173        3717 :         wpa_supplicant_notify_scanning(wpa_s, 1);
     174             : 
     175        3717 :         if (wpa_s->clear_driver_scan_cache) {
     176        2297 :                 wpa_printf(MSG_DEBUG,
     177             :                            "Request driver to clear scan cache due to local BSS flush");
     178        2297 :                 params->only_new_results = 1;
     179             :         }
     180        3717 :         ret = wpa_drv_scan(wpa_s, params);
     181        3717 :         wpa_scan_free_params(params);
     182        3717 :         work->ctx = NULL;
     183        3717 :         if (ret) {
     184           5 :                 int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ;
     185             : 
     186           5 :                 if (wpa_s->disconnected)
     187           0 :                         retry = 0;
     188             : 
     189           5 :                 wpa_supplicant_notify_scanning(wpa_s, 0);
     190           5 :                 wpas_notify_scan_done(wpa_s, 0);
     191           5 :                 if (wpa_s->wpa_state == WPA_SCANNING)
     192           2 :                         wpa_supplicant_set_state(wpa_s,
     193             :                                                  wpa_s->scan_prev_wpa_state);
     194           5 :                 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=%d%s",
     195             :                         ret, retry ? " retry=1" : "");
     196           5 :                 radio_work_done(work);
     197             : 
     198           5 :                 if (retry) {
     199             :                         /* Restore scan_req since we will try to scan again */
     200           1 :                         wpa_s->scan_req = wpa_s->last_scan_req;
     201           1 :                         wpa_supplicant_req_scan(wpa_s, 1, 0);
     202             :                 }
     203           5 :                 return;
     204             :         }
     205             : 
     206        3712 :         os_get_reltime(&wpa_s->scan_trigger_time);
     207        3712 :         wpa_s->scan_runs++;
     208        3712 :         wpa_s->normal_scans++;
     209        3712 :         wpa_s->own_scan_requested = 1;
     210        3712 :         wpa_s->clear_driver_scan_cache = 0;
     211        3712 :         wpa_s->scan_work = work;
     212             : }
     213             : 
     214             : 
     215             : /**
     216             :  * wpa_supplicant_trigger_scan - Request driver to start a scan
     217             :  * @wpa_s: Pointer to wpa_supplicant data
     218             :  * @params: Scan parameters
     219             :  * Returns: 0 on success, -1 on failure
     220             :  */
     221        3719 : int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
     222             :                                 struct wpa_driver_scan_params *params)
     223             : {
     224             :         struct wpa_driver_scan_params *ctx;
     225             : 
     226        3719 :         if (wpa_s->scan_work) {
     227           1 :                 wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending");
     228           1 :                 return -1;
     229             :         }
     230             : 
     231        3718 :         ctx = wpa_scan_clone_params(params);
     232        3718 :         if (ctx == NULL)
     233           1 :                 return -1;
     234             : 
     235        3717 :         if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
     236             :         {
     237           0 :                 wpa_scan_free_params(ctx);
     238           0 :                 return -1;
     239             :         }
     240             : 
     241        3717 :         return 0;
     242             : }
     243             : 
     244             : 
     245             : static void
     246           0 : wpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
     247             : {
     248           0 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     249             : 
     250           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan");
     251             : 
     252           0 :         if (wpa_supplicant_req_sched_scan(wpa_s))
     253           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
     254           0 : }
     255             : 
     256             : 
     257             : static void
     258           0 : wpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx)
     259             : {
     260           0 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     261             : 
     262           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it");
     263             : 
     264           0 :         wpa_s->sched_scan_timed_out = 1;
     265           0 :         wpa_supplicant_cancel_sched_scan(wpa_s);
     266           0 : }
     267             : 
     268             : 
     269           0 : int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
     270             :                                     struct wpa_driver_scan_params *params,
     271             :                                     int interval)
     272             : {
     273             :         int ret;
     274             : 
     275           0 :         wpa_supplicant_notify_scanning(wpa_s, 1);
     276           0 :         ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
     277           0 :         if (ret)
     278           0 :                 wpa_supplicant_notify_scanning(wpa_s, 0);
     279             :         else
     280           0 :                 wpa_s->sched_scanning = 1;
     281             : 
     282           0 :         return ret;
     283             : }
     284             : 
     285             : 
     286           0 : int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
     287             : {
     288             :         int ret;
     289             : 
     290           0 :         ret = wpa_drv_stop_sched_scan(wpa_s);
     291           0 :         if (ret) {
     292           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!");
     293             :                 /* TODO: what to do if stopping fails? */
     294           0 :                 return -1;
     295             :         }
     296             : 
     297           0 :         return ret;
     298             : }
     299             : 
     300             : 
     301             : static struct wpa_driver_scan_filter *
     302        3703 : wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
     303             : {
     304             :         struct wpa_driver_scan_filter *ssids;
     305             :         struct wpa_ssid *ssid;
     306             :         size_t count;
     307             : 
     308        3703 :         *num_ssids = 0;
     309        3703 :         if (!conf->filter_ssids)
     310        3700 :                 return NULL;
     311             : 
     312           7 :         for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
     313           4 :                 if (ssid->ssid && ssid->ssid_len)
     314           2 :                         count++;
     315             :         }
     316           3 :         if (count == 0)
     317           1 :                 return NULL;
     318           2 :         ssids = os_calloc(count, sizeof(struct wpa_driver_scan_filter));
     319           2 :         if (ssids == NULL)
     320           0 :                 return NULL;
     321             : 
     322           5 :         for (ssid = conf->ssid; ssid; ssid = ssid->next) {
     323           3 :                 if (!ssid->ssid || !ssid->ssid_len)
     324           1 :                         continue;
     325           2 :                 os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
     326           2 :                 ssids[*num_ssids].ssid_len = ssid->ssid_len;
     327           2 :                 (*num_ssids)++;
     328             :         }
     329             : 
     330           2 :         return ssids;
     331             : }
     332             : 
     333             : 
     334        3703 : static void wpa_supplicant_optimize_freqs(
     335             :         struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params)
     336             : {
     337             : #ifdef CONFIG_P2P
     338        3929 :         if (params->freqs == NULL && wpa_s->p2p_in_provisioning &&
     339         226 :             wpa_s->go_params) {
     340             :                 /* Optimize provisioning state scan based on GO information */
     341         442 :                 if (wpa_s->p2p_in_provisioning < 5 &&
     342         216 :                     wpa_s->go_params->freq > 0) {
     343         216 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO "
     344             :                                 "preferred frequency %d MHz",
     345             :                                 wpa_s->go_params->freq);
     346         216 :                         params->freqs = os_calloc(2, sizeof(int));
     347         432 :                         if (params->freqs)
     348         216 :                                 params->freqs[0] = wpa_s->go_params->freq;
     349          17 :                 } else if (wpa_s->p2p_in_provisioning < 8 &&
     350           7 :                            wpa_s->go_params->freq_list[0]) {
     351           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common "
     352             :                                 "channels");
     353           0 :                         int_array_concat(&params->freqs,
     354           0 :                                          wpa_s->go_params->freq_list);
     355           0 :                         if (params->freqs)
     356           0 :                                 int_array_sort_unique(params->freqs);
     357             :                 }
     358         226 :                 wpa_s->p2p_in_provisioning++;
     359             :         }
     360             : 
     361        3703 :         if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
     362             :                 /*
     363             :                  * Optimize scan based on GO information during persistent
     364             :                  * group reinvocation
     365             :                  */
     366         101 :                 if (wpa_s->p2p_in_invitation < 5 &&
     367          48 :                     wpa_s->p2p_invite_go_freq > 0) {
     368          48 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
     369             :                                 wpa_s->p2p_invite_go_freq);
     370          48 :                         params->freqs = os_calloc(2, sizeof(int));
     371          48 :                         if (params->freqs)
     372          48 :                                 params->freqs[0] = wpa_s->p2p_invite_go_freq;
     373             :                 }
     374          53 :                 wpa_s->p2p_in_invitation++;
     375          53 :                 if (wpa_s->p2p_in_invitation > 20) {
     376             :                         /*
     377             :                          * This should not really happen since the variable is
     378             :                          * cleared on group removal, but if it does happen, make
     379             :                          * sure we do not get stuck in special invitation scan
     380             :                          * mode.
     381             :                          */
     382           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
     383           0 :                         wpa_s->p2p_in_invitation = 0;
     384             :                 }
     385             :         }
     386             : #endif /* CONFIG_P2P */
     387             : 
     388             : #ifdef CONFIG_WPS
     389        3703 :         if (params->freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
     390             :                 /*
     391             :                  * Optimize post-provisioning scan based on channel used
     392             :                  * during provisioning.
     393             :                  */
     394          25 :                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz "
     395             :                         "that was used during provisioning", wpa_s->wps_freq);
     396          25 :                 params->freqs = os_calloc(2, sizeof(int));
     397          25 :                 if (params->freqs)
     398          25 :                         params->freqs[0] = wpa_s->wps_freq;
     399          25 :                 wpa_s->after_wps--;
     400        3678 :         } else if (wpa_s->after_wps)
     401           1 :                 wpa_s->after_wps--;
     402             : 
     403        3703 :         if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
     404             :         {
     405             :                 /* Optimize provisioning scan based on already known channel */
     406         303 :                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Scan only frequency %u MHz",
     407             :                         wpa_s->wps_freq);
     408         303 :                 params->freqs = os_calloc(2, sizeof(int));
     409         303 :                 if (params->freqs)
     410         303 :                         params->freqs[0] = wpa_s->wps_freq;
     411         303 :                 wpa_s->known_wps_freq = 0; /* only do this once */
     412             :         }
     413             : #endif /* CONFIG_WPS */
     414        3703 : }
     415             : 
     416             : 
     417             : #ifdef CONFIG_INTERWORKING
     418         810 : static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
     419             :                                            struct wpabuf *buf)
     420             : {
     421         810 :         wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
     422         810 :         wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
     423             :                       1 + ETH_ALEN);
     424         810 :         wpabuf_put_u8(buf, wpa_s->conf->access_network_type);
     425             :         /* No Venue Info */
     426         810 :         if (!is_zero_ether_addr(wpa_s->conf->hessid))
     427           4 :                 wpabuf_put_data(buf, wpa_s->conf->hessid, ETH_ALEN);
     428         810 : }
     429             : #endif /* CONFIG_INTERWORKING */
     430             : 
     431             : 
     432        3703 : static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
     433             : {
     434        3703 :         struct wpabuf *extra_ie = NULL;
     435             :         u8 ext_capab[18];
     436             :         int ext_capab_len;
     437             : #ifdef CONFIG_WPS
     438        3703 :         int wps = 0;
     439        3703 :         enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
     440             : #endif /* CONFIG_WPS */
     441             : 
     442        3703 :         ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
     443             :                                              sizeof(ext_capab));
     444        7406 :         if (ext_capab_len > 0 &&
     445        3703 :             wpabuf_resize(&extra_ie, ext_capab_len) == 0)
     446        3703 :                 wpabuf_put_data(extra_ie, ext_capab, ext_capab_len);
     447             : 
     448             : #ifdef CONFIG_INTERWORKING
     449        4513 :         if (wpa_s->conf->interworking &&
     450         810 :             wpabuf_resize(&extra_ie, 100) == 0)
     451         810 :                 wpas_add_interworking_elements(wpa_s, extra_ie);
     452             : #endif /* CONFIG_INTERWORKING */
     453             : 
     454             : #ifdef CONFIG_WPS
     455        3703 :         wps = wpas_wps_in_use(wpa_s, &req_type);
     456             : 
     457        3703 :         if (wps) {
     458             :                 struct wpabuf *wps_ie;
     459        7372 :                 wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
     460             :                                                 DEV_PW_DEFAULT,
     461        3686 :                                                 &wpa_s->wps->dev,
     462        3686 :                                                 wpa_s->wps->uuid, req_type,
     463             :                                                 0, NULL);
     464        3686 :                 if (wps_ie) {
     465        3684 :                         if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
     466        3684 :                                 wpabuf_put_buf(extra_ie, wps_ie);
     467        3684 :                         wpabuf_free(wps_ie);
     468             :                 }
     469             :         }
     470             : 
     471             : #ifdef CONFIG_P2P
     472        3703 :         if (wps) {
     473        3686 :                 size_t ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
     474        3686 :                 if (wpabuf_resize(&extra_ie, ielen) == 0)
     475        3686 :                         wpas_p2p_scan_ie(wpa_s, extra_ie);
     476             :         }
     477             : #endif /* CONFIG_P2P */
     478             : 
     479        3703 :         wpa_supplicant_mesh_add_scan_ie(wpa_s, &extra_ie);
     480             : 
     481             : #endif /* CONFIG_WPS */
     482             : 
     483             : #ifdef CONFIG_HS20
     484        3703 :         if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
     485         810 :                 wpas_hs20_add_indication(extra_ie, -1);
     486             : #endif /* CONFIG_HS20 */
     487             : 
     488             : #ifdef CONFIG_FST
     489        3957 :         if (wpa_s->fst_ies &&
     490         254 :             wpabuf_resize(&extra_ie, wpabuf_len(wpa_s->fst_ies)) == 0)
     491         254 :                 wpabuf_put_buf(extra_ie, wpa_s->fst_ies);
     492             : #endif /* CONFIG_FST */
     493             : 
     494        3703 :         return extra_ie;
     495             : }
     496             : 
     497             : 
     498             : #ifdef CONFIG_P2P
     499             : 
     500             : /*
     501             :  * Check whether there are any enabled networks or credentials that could be
     502             :  * used for a non-P2P connection.
     503             :  */
     504          51 : static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
     505             : {
     506             :         struct wpa_ssid *ssid;
     507             : 
     508          64 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
     509          58 :                 if (wpas_network_disabled(wpa_s, ssid))
     510           7 :                         continue;
     511          51 :                 if (!ssid->p2p_group)
     512          45 :                         return 1;
     513             :         }
     514             : 
     515           6 :         if (wpa_s->conf->cred && wpa_s->conf->interworking &&
     516           0 :             wpa_s->conf->auto_interworking)
     517           0 :                 return 1;
     518             : 
     519           6 :         return 0;
     520             : }
     521             : 
     522             : #endif /* CONFIG_P2P */
     523             : 
     524             : 
     525           2 : static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
     526             :                                           u16 num_modes,
     527             :                                           enum hostapd_hw_mode mode)
     528             : {
     529             :         u16 i;
     530             : 
     531           3 :         for (i = 0; i < num_modes; i++) {
     532           3 :                 if (modes[i].mode == mode)
     533           2 :                         return &modes[i];
     534             :         }
     535             : 
     536           0 :         return NULL;
     537             : }
     538             : 
     539             : 
     540           2 : static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
     541             :                                         enum hostapd_hw_mode band,
     542             :                                         struct wpa_driver_scan_params *params)
     543             : {
     544             :         /* Include only supported channels for the specified band */
     545             :         struct hostapd_hw_modes *mode;
     546             :         int count, i;
     547             : 
     548           2 :         mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
     549           2 :         if (mode == NULL) {
     550             :                 /* No channels supported in this band - use empty list */
     551           0 :                 params->freqs = os_zalloc(sizeof(int));
     552           0 :                 return;
     553             :         }
     554             : 
     555           2 :         params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
     556           2 :         if (params->freqs == NULL)
     557           0 :                 return;
     558          40 :         for (count = 0, i = 0; i < mode->num_channels; i++) {
     559          38 :                 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
     560          14 :                         continue;
     561          24 :                 params->freqs[count++] = mode->channels[i].freq;
     562             :         }
     563             : }
     564             : 
     565             : 
     566        3703 : static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
     567             :                                    struct wpa_driver_scan_params *params)
     568             : {
     569        3703 :         if (wpa_s->hw.modes == NULL)
     570          15 :                 return; /* unknown what channels the driver supports */
     571        3688 :         if (params->freqs)
     572        3482 :                 return; /* already using a limited channel set */
     573         206 :         if (wpa_s->setband == WPA_SETBAND_5G)
     574           1 :                 wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
     575             :                                             params);
     576         205 :         else if (wpa_s->setband == WPA_SETBAND_2G)
     577           1 :                 wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
     578             :                                             params);
     579             : }
     580             : 
     581             : 
     582           2 : static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
     583             :                                struct wpa_driver_scan_params *params,
     584             :                                size_t max_ssids)
     585             : {
     586             :         unsigned int i;
     587             :         struct wpa_ssid *ssid;
     588             : 
     589           6 :         for (i = 0; i < wpa_s->scan_id_count; i++) {
     590             :                 unsigned int j;
     591             : 
     592           4 :                 ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
     593           4 :                 if (!ssid || !ssid->scan_ssid)
     594           1 :                         continue;
     595             : 
     596           4 :                 for (j = 0; j < params->num_ssids; j++) {
     597           1 :                         if (params->ssids[j].ssid_len == ssid->ssid_len &&
     598           0 :                             params->ssids[j].ssid &&
     599           0 :                             os_memcmp(params->ssids[j].ssid, ssid->ssid,
     600             :                                       ssid->ssid_len) == 0)
     601           0 :                                 break;
     602             :                 }
     603           3 :                 if (j < params->num_ssids)
     604           0 :                         continue; /* already in the list */
     605             : 
     606           3 :                 if (params->num_ssids + 1 > max_ssids) {
     607           0 :                         wpa_printf(MSG_DEBUG,
     608             :                                    "Over max scan SSIDs for manual request");
     609           0 :                         break;
     610             :                 }
     611             : 
     612           6 :                 wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
     613           3 :                            wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
     614           3 :                 params->ssids[params->num_ssids].ssid = ssid->ssid;
     615           3 :                 params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
     616           3 :                 params->num_ssids++;
     617             :         }
     618             : 
     619           2 :         wpa_s->scan_id_count = 0;
     620           2 : }
     621             : 
     622             : 
     623        1874 : static int wpa_set_ssids_from_scan_req(struct wpa_supplicant *wpa_s,
     624             :                                        struct wpa_driver_scan_params *params,
     625             :                                        size_t max_ssids)
     626             : {
     627             :         unsigned int i;
     628             : 
     629        1876 :         if (wpa_s->ssids_from_scan_req == NULL ||
     630           2 :             wpa_s->num_ssids_from_scan_req == 0)
     631        1872 :                 return 0;
     632             : 
     633           2 :         if (wpa_s->num_ssids_from_scan_req > max_ssids) {
     634           0 :                 wpa_s->num_ssids_from_scan_req = max_ssids;
     635           0 :                 wpa_printf(MSG_DEBUG, "Over max scan SSIDs from scan req: %u",
     636             :                            (unsigned int) max_ssids);
     637             :         }
     638             : 
     639           6 :         for (i = 0; i < wpa_s->num_ssids_from_scan_req; i++) {
     640           4 :                 params->ssids[i].ssid = wpa_s->ssids_from_scan_req[i].ssid;
     641           4 :                 params->ssids[i].ssid_len =
     642           4 :                         wpa_s->ssids_from_scan_req[i].ssid_len;
     643           8 :                 wpa_hexdump_ascii(MSG_DEBUG, "specific SSID",
     644           4 :                                   params->ssids[i].ssid,
     645             :                                   params->ssids[i].ssid_len);
     646             :         }
     647             : 
     648           2 :         params->num_ssids = wpa_s->num_ssids_from_scan_req;
     649           2 :         wpa_s->num_ssids_from_scan_req = 0;
     650           2 :         return 1;
     651             : }
     652             : 
     653             : 
     654        4856 : static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
     655             : {
     656        4856 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     657             :         struct wpa_ssid *ssid;
     658             :         int ret, p2p_in_prog;
     659        4856 :         struct wpabuf *extra_ie = NULL;
     660             :         struct wpa_driver_scan_params params;
     661             :         struct wpa_driver_scan_params *scan_params;
     662             :         size_t max_ssids;
     663        4856 :         int connect_without_scan = 0;
     664             : 
     665        4856 :         if (wpa_s->pno || wpa_s->pno_sched_pending) {
     666           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
     667           0 :                 return;
     668             :         }
     669             : 
     670        4856 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
     671           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
     672           0 :                 return;
     673             :         }
     674             : 
     675        4856 :         if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
     676           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
     677           0 :                 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
     678           0 :                 return;
     679             :         }
     680             : 
     681        4856 :         if (wpa_s->scanning) {
     682             :                 /*
     683             :                  * If we are already in scanning state, we shall reschedule the
     684             :                  * the incoming scan request.
     685             :                  */
     686           4 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req");
     687           4 :                 wpa_supplicant_req_scan(wpa_s, 1, 0);
     688           4 :                 return;
     689             :         }
     690             : 
     691        7304 :         if (!wpa_supplicant_enabled_networks(wpa_s) &&
     692        2452 :             wpa_s->scan_req == NORMAL_SCAN_REQ) {
     693         774 :                 wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
     694         774 :                 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
     695         774 :                 return;
     696             :         }
     697             : 
     698        8154 :         if (wpa_s->conf->ap_scan != 0 &&
     699        4076 :             (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
     700           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - "
     701             :                         "overriding ap_scan configuration");
     702           0 :                 wpa_s->conf->ap_scan = 0;
     703           0 :                 wpas_notify_ap_scan_changed(wpa_s);
     704             :         }
     705             : 
     706        4078 :         if (wpa_s->conf->ap_scan == 0) {
     707           2 :                 wpa_supplicant_gen_assoc_event(wpa_s);
     708           2 :                 return;
     709             :         }
     710             : 
     711        4076 :         ssid = NULL;
     712        6277 :         if (wpa_s->scan_req != MANUAL_SCAN_REQ &&
     713        2201 :             wpa_s->connect_without_scan) {
     714         357 :                 connect_without_scan = 1;
     715         392 :                 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
     716         392 :                         if (ssid == wpa_s->connect_without_scan)
     717         357 :                                 break;
     718             :                 }
     719             :         }
     720             : 
     721        4076 :         p2p_in_prog = wpas_p2p_in_progress(wpa_s);
     722        4076 :         if (p2p_in_prog && p2p_in_prog != 2 &&
     723          62 :             (!ssid ||
     724         124 :              (ssid->mode != WPAS_MODE_AP && ssid->mode != WPAS_MODE_P2P_GO))) {
     725           1 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
     726           1 :                 wpa_supplicant_req_scan(wpa_s, 5, 0);
     727           1 :                 return;
     728             :         }
     729             : 
     730        4075 :         if (wpa_s->conf->ap_scan == 2)
     731          19 :                 max_ssids = 1;
     732             :         else {
     733        4056 :                 max_ssids = wpa_s->max_scan_ssids;
     734        4056 :                 if (max_ssids > WPAS_MAX_SCAN_SSIDS)
     735          16 :                         max_ssids = WPAS_MAX_SCAN_SSIDS;
     736             :         }
     737             : 
     738        4075 :         wpa_s->last_scan_req = wpa_s->scan_req;
     739        4075 :         wpa_s->scan_req = NORMAL_SCAN_REQ;
     740             : 
     741        4075 :         if (connect_without_scan) {
     742         357 :                 wpa_s->connect_without_scan = NULL;
     743         357 :                 if (ssid) {
     744         357 :                         wpa_printf(MSG_DEBUG, "Start a pre-selected network "
     745             :                                    "without scan step");
     746         357 :                         wpa_supplicant_associate(wpa_s, NULL, ssid);
     747         357 :                         return;
     748             :                 }
     749             :         }
     750             : 
     751        3718 :         os_memset(&params, 0, sizeof(params));
     752             : 
     753        3718 :         wpa_s->scan_prev_wpa_state = wpa_s->wpa_state;
     754        5982 :         if (wpa_s->wpa_state == WPA_DISCONNECTED ||
     755        2264 :             wpa_s->wpa_state == WPA_INACTIVE)
     756        2354 :                 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
     757             : 
     758             :         /*
     759             :          * If autoscan has set its own scanning parameters
     760             :          */
     761        3718 :         if (wpa_s->autoscan_params != NULL) {
     762           0 :                 scan_params = wpa_s->autoscan_params;
     763           0 :                 goto scan;
     764             :         }
     765             : 
     766        5592 :         if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
     767        1874 :             wpa_set_ssids_from_scan_req(wpa_s, &params, max_ssids)) {
     768           2 :                 wpa_printf(MSG_DEBUG, "Use specific SSIDs from SCAN command");
     769           2 :                 goto ssid_list_set;
     770             :         }
     771             : 
     772             : #ifdef CONFIG_P2P
     773        3995 :         if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
     774         505 :             wpa_s->go_params && !wpa_s->conf->passive_scan) {
     775         220 :                 wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)",
     776             :                            wpa_s->p2p_in_provisioning,
     777             :                            wpa_s->show_group_started);
     778         220 :                 params.ssids[0].ssid = wpa_s->go_params->ssid;
     779         220 :                 params.ssids[0].ssid_len = wpa_s->go_params->ssid_len;
     780         220 :                 params.num_ssids = 1;
     781         220 :                 goto ssid_list_set;
     782             :         }
     783             : 
     784        3496 :         if (wpa_s->p2p_in_invitation) {
     785          53 :                 if (wpa_s->current_ssid) {
     786          42 :                         wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation");
     787          42 :                         params.ssids[0].ssid = wpa_s->current_ssid->ssid;
     788          42 :                         params.ssids[0].ssid_len =
     789          42 :                                 wpa_s->current_ssid->ssid_len;
     790          42 :                         params.num_ssids = 1;
     791             :                 } else {
     792          11 :                         wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation");
     793             :                 }
     794          53 :                 goto ssid_list_set;
     795             :         }
     796             : #endif /* CONFIG_P2P */
     797             : 
     798             :         /* Find the starting point from which to continue scanning */
     799        3443 :         ssid = wpa_s->conf->ssid;
     800        3443 :         if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
     801           8 :                 while (ssid) {
     802           4 :                         if (ssid == wpa_s->prev_scan_ssid) {
     803           2 :                                 ssid = ssid->next;
     804           2 :                                 break;
     805             :                         }
     806           2 :                         ssid = ssid->next;
     807             :                 }
     808             :         }
     809             : 
     810        5014 :         if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
     811             : #ifdef CONFIG_AP
     812        3142 :             !wpa_s->ap_iface &&
     813             : #endif /* CONFIG_AP */
     814        1571 :             wpa_s->conf->ap_scan == 2) {
     815          15 :                 wpa_s->connect_without_scan = NULL;
     816          15 :                 wpa_s->prev_scan_wildcard = 0;
     817          15 :                 wpa_supplicant_assoc_try(wpa_s, ssid);
     818          15 :                 return;
     819        3428 :         } else if (wpa_s->conf->ap_scan == 2) {
     820             :                 /*
     821             :                  * User-initiated scan request in ap_scan == 2; scan with
     822             :                  * wildcard SSID.
     823             :                  */
     824           4 :                 ssid = NULL;
     825        3424 :         } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
     826             :                 /*
     827             :                  * Perform single-channel single-SSID scan for
     828             :                  * reassociate-to-same-BSS operation.
     829             :                  */
     830             :                 /* Setup SSID */
     831           0 :                 ssid = wpa_s->current_ssid;
     832           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
     833           0 :                                   ssid->ssid, ssid->ssid_len);
     834           0 :                 params.ssids[0].ssid = ssid->ssid;
     835           0 :                 params.ssids[0].ssid_len = ssid->ssid_len;
     836           0 :                 params.num_ssids = 1;
     837             : 
     838             :                 /*
     839             :                  * Allocate memory for frequency array, allocate one extra
     840             :                  * slot for the zero-terminator.
     841             :                  */
     842           0 :                 params.freqs = os_malloc(sizeof(int) * 2);
     843           0 :                 if (params.freqs == NULL) {
     844           0 :                         wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
     845           0 :                         return;
     846             :                 }
     847           0 :                 params.freqs[0] = wpa_s->assoc_freq;
     848           0 :                 params.freqs[1] = 0;
     849             : 
     850             :                 /*
     851             :                  * Reset the reattach flag so that we fall back to full scan if
     852             :                  * this scan fails.
     853             :                  */
     854           0 :                 wpa_s->reattach = 0;
     855             :         } else {
     856        3424 :                 struct wpa_ssid *start = ssid, *tssid;
     857        3424 :                 int freqs_set = 0;
     858        3424 :                 if (ssid == NULL && max_ssids > 1)
     859        1660 :                         ssid = wpa_s->conf->ssid;
     860        8651 :                 while (ssid) {
     861        3563 :                         if (!wpas_network_disabled(wpa_s, ssid) &&
     862        1756 :                             ssid->scan_ssid) {
     863          28 :                                 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
     864          14 :                                                   ssid->ssid, ssid->ssid_len);
     865          28 :                                 params.ssids[params.num_ssids].ssid =
     866          14 :                                         ssid->ssid;
     867          28 :                                 params.ssids[params.num_ssids].ssid_len =
     868          14 :                                         ssid->ssid_len;
     869          14 :                                 params.num_ssids++;
     870          14 :                                 if (params.num_ssids + 1 >= max_ssids)
     871           4 :                                         break;
     872             :                         }
     873        1803 :                         ssid = ssid->next;
     874        1803 :                         if (ssid == start)
     875           0 :                                 break;
     876        3550 :                         if (ssid == NULL && max_ssids > 1 &&
     877        1747 :                             start != wpa_s->conf->ssid)
     878           0 :                                 ssid = wpa_s->conf->ssid;
     879             :                 }
     880             : 
     881        3426 :                 if (wpa_s->scan_id_count &&
     882           2 :                     wpa_s->last_scan_req == MANUAL_SCAN_REQ)
     883           2 :                         wpa_set_scan_ssids(wpa_s, &params, max_ssids);
     884             : 
     885        8449 :                 for (tssid = wpa_s->conf->ssid;
     886        8182 :                      wpa_s->last_scan_req != MANUAL_SCAN_REQ && tssid;
     887        1601 :                      tssid = tssid->next) {
     888        1601 :                         if (wpas_network_disabled(wpa_s, tssid))
     889          29 :                                 continue;
     890        1572 :                         if ((params.freqs || !freqs_set) && tssid->scan_freq) {
     891        1075 :                                 int_array_concat(&params.freqs,
     892        1075 :                                                  tssid->scan_freq);
     893             :                         } else {
     894         497 :                                 os_free(params.freqs);
     895         497 :                                 params.freqs = NULL;
     896             :                         }
     897        1572 :                         freqs_set = 1;
     898             :                 }
     899        3424 :                 int_array_sort_unique(params.freqs);
     900             :         }
     901             : 
     902        3428 :         if (ssid && max_ssids == 1) {
     903             :                 /*
     904             :                  * If the driver is limited to 1 SSID at a time interleave
     905             :                  * wildcard SSID scans with specific SSID scans to avoid
     906             :                  * waiting a long time for a wildcard scan.
     907             :                  */
     908           4 :                 if (!wpa_s->prev_scan_wildcard) {
     909           1 :                         params.ssids[0].ssid = NULL;
     910           1 :                         params.ssids[0].ssid_len = 0;
     911           1 :                         wpa_s->prev_scan_wildcard = 1;
     912           1 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for "
     913             :                                 "wildcard SSID (Interleave with specific)");
     914             :                 } else {
     915           1 :                         wpa_s->prev_scan_ssid = ssid;
     916           1 :                         wpa_s->prev_scan_wildcard = 0;
     917           1 :                         wpa_dbg(wpa_s, MSG_DEBUG,
     918             :                                 "Starting AP scan for specific SSID: %s",
     919             :                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
     920             :                 }
     921        3426 :         } else if (ssid) {
     922             :                 /* max_ssids > 1 */
     923             : 
     924           2 :                 wpa_s->prev_scan_ssid = ssid;
     925           2 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
     926             :                         "the scan request");
     927           2 :                 params.num_ssids++;
     928        3424 :         } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
     929          11 :                    wpa_s->manual_scan_passive && params.num_ssids == 0) {
     930          11 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request");
     931        3413 :         } else if (wpa_s->conf->passive_scan) {
     932           6 :                 wpa_dbg(wpa_s, MSG_DEBUG,
     933             :                         "Use passive scan based on configuration");
     934             :         } else {
     935        3407 :                 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
     936        3407 :                 params.num_ssids++;
     937        3407 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard "
     938             :                         "SSID");
     939             :         }
     940             : 
     941             : ssid_list_set:
     942        3703 :         wpa_supplicant_optimize_freqs(wpa_s, &params);
     943        3703 :         extra_ie = wpa_supplicant_extra_ies(wpa_s);
     944             : 
     945        3703 :         if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
     946             :             wpa_s->manual_scan_only_new) {
     947         907 :                 wpa_printf(MSG_DEBUG,
     948             :                            "Request driver to clear scan cache due to manual only_new=1 scan");
     949         907 :                 params.only_new_results = 1;
     950             :         }
     951             : 
     952        5576 :         if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
     953        1873 :             wpa_s->manual_scan_freqs) {
     954        1834 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
     955        1834 :                 params.freqs = wpa_s->manual_scan_freqs;
     956        1834 :                 wpa_s->manual_scan_freqs = NULL;
     957             :         }
     958             : 
     959        3703 :         if (params.freqs == NULL && wpa_s->next_scan_freqs) {
     960           7 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
     961             :                         "generated frequency list");
     962           7 :                 params.freqs = wpa_s->next_scan_freqs;
     963             :         } else
     964        3696 :                 os_free(wpa_s->next_scan_freqs);
     965        3703 :         wpa_s->next_scan_freqs = NULL;
     966        3703 :         wpa_setband_scan_freqs(wpa_s, &params);
     967             : 
     968             :         /* See if user specified frequencies. If so, scan only those. */
     969        3703 :         if (wpa_s->conf->freq_list && !params.freqs) {
     970           0 :                 wpa_dbg(wpa_s, MSG_DEBUG,
     971             :                         "Optimize scan based on conf->freq_list");
     972           0 :                 int_array_concat(&params.freqs, wpa_s->conf->freq_list);
     973             :         }
     974             : 
     975             :         /* Use current associated channel? */
     976        3703 :         if (wpa_s->conf->scan_cur_freq && !params.freqs) {
     977           0 :                 unsigned int num = wpa_s->num_multichan_concurrent;
     978             : 
     979           0 :                 params.freqs = os_calloc(num + 1, sizeof(int));
     980           0 :                 if (params.freqs) {
     981           0 :                         num = get_shared_radio_freqs(wpa_s, params.freqs, num);
     982           0 :                         if (num > 0) {
     983           0 :                                 wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
     984             :                                         "current operating channels since "
     985             :                                         "scan_cur_freq is enabled");
     986             :                         } else {
     987           0 :                                 os_free(params.freqs);
     988           0 :                                 params.freqs = NULL;
     989             :                         }
     990             :                 }
     991             :         }
     992             : 
     993        3703 :         params.filter_ssids = wpa_supplicant_build_filter_ssids(
     994             :                 wpa_s->conf, &params.num_filter_ssids);
     995        3703 :         if (extra_ie) {
     996        3703 :                 params.extra_ies = wpabuf_head(extra_ie);
     997        3703 :                 params.extra_ies_len = wpabuf_len(extra_ie);
     998             :         }
     999             : 
    1000             : #ifdef CONFIG_P2P
    1001        7127 :         if (wpa_s->p2p_in_provisioning || wpa_s->p2p_in_invitation ||
    1002        3424 :             (wpa_s->show_group_started && wpa_s->go_params)) {
    1003             :                 /*
    1004             :                  * The interface may not yet be in P2P mode, so we have to
    1005             :                  * explicitly request P2P probe to disable CCK rates.
    1006             :                  */
    1007         279 :                 params.p2p_probe = 1;
    1008             :         }
    1009             : #endif /* CONFIG_P2P */
    1010             : 
    1011        3703 :         if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) {
    1012           3 :                 params.mac_addr_rand = 1;
    1013           3 :                 if (wpa_s->mac_addr_scan) {
    1014           2 :                         params.mac_addr = wpa_s->mac_addr_scan;
    1015           2 :                         params.mac_addr_mask = wpa_s->mac_addr_scan + ETH_ALEN;
    1016             :                 }
    1017             :         }
    1018             : 
    1019        3703 :         scan_params = &params;
    1020             : 
    1021             : scan:
    1022             : #ifdef CONFIG_P2P
    1023             :         /*
    1024             :          * If the driver does not support multi-channel concurrency and a
    1025             :          * virtual interface that shares the same radio with the wpa_s interface
    1026             :          * is operating there may not be need to scan other channels apart from
    1027             :          * the current operating channel on the other virtual interface. Filter
    1028             :          * out other channels in case we are trying to find a connection for a
    1029             :          * station interface when we are not configured to prefer station
    1030             :          * connection and a concurrent operation is already in process.
    1031             :          */
    1032        3976 :         if (wpa_s->scan_for_connection &&
    1033         517 :             wpa_s->last_scan_req == NORMAL_SCAN_REQ &&
    1034         352 :             !scan_params->freqs && !params.freqs &&
    1035         108 :             wpas_is_p2p_prioritized(wpa_s) &&
    1036         105 :             wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
    1037          51 :             non_p2p_network_enabled(wpa_s)) {
    1038          45 :                 unsigned int num = wpa_s->num_multichan_concurrent;
    1039             : 
    1040          45 :                 params.freqs = os_calloc(num + 1, sizeof(int));
    1041          45 :                 if (params.freqs) {
    1042          45 :                         num = get_shared_radio_freqs(wpa_s, params.freqs, num);
    1043          45 :                         if (num > 0 && num == wpa_s->num_multichan_concurrent) {
    1044           0 :                                 wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used");
    1045             :                         } else {
    1046          45 :                                 os_free(params.freqs);
    1047          45 :                                 params.freqs = NULL;
    1048             :                         }
    1049             :                 }
    1050             :         }
    1051             : #endif /* CONFIG_P2P */
    1052             : 
    1053        3703 :         ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
    1054             : 
    1055        3703 :         if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
    1056           0 :             !wpa_s->manual_scan_freqs) {
    1057             :                 /* Restore manual_scan_freqs for the next attempt */
    1058           0 :                 wpa_s->manual_scan_freqs = params.freqs;
    1059           0 :                 params.freqs = NULL;
    1060             :         }
    1061             : 
    1062        3703 :         wpabuf_free(extra_ie);
    1063        3703 :         os_free(params.freqs);
    1064        3703 :         os_free(params.filter_ssids);
    1065             : 
    1066        3703 :         if (ret) {
    1067           0 :                 wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
    1068           0 :                 if (wpa_s->scan_prev_wpa_state != wpa_s->wpa_state)
    1069           0 :                         wpa_supplicant_set_state(wpa_s,
    1070             :                                                  wpa_s->scan_prev_wpa_state);
    1071             :                 /* Restore scan_req since we will try to scan again */
    1072           0 :                 wpa_s->scan_req = wpa_s->last_scan_req;
    1073           0 :                 wpa_supplicant_req_scan(wpa_s, 1, 0);
    1074             :         } else {
    1075        3703 :                 wpa_s->scan_for_connection = 0;
    1076             : #ifdef CONFIG_INTERWORKING
    1077        3703 :                 wpa_s->interworking_fast_assoc_tried = 0;
    1078             : #endif /* CONFIG_INTERWORKING */
    1079             :         }
    1080             : }
    1081             : 
    1082             : 
    1083          23 : void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec)
    1084             : {
    1085             :         struct os_reltime remaining, new_int;
    1086             :         int cancelled;
    1087             : 
    1088          23 :         cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL,
    1089             :                                              &remaining);
    1090             : 
    1091          23 :         new_int.sec = sec;
    1092          23 :         new_int.usec = 0;
    1093          23 :         if (cancelled && os_reltime_before(&remaining, &new_int)) {
    1094           6 :                 new_int.sec = remaining.sec;
    1095           6 :                 new_int.usec = remaining.usec;
    1096             :         }
    1097             : 
    1098          23 :         if (cancelled) {
    1099           6 :                 eloop_register_timeout(new_int.sec, new_int.usec,
    1100             :                                        wpa_supplicant_scan, wpa_s, NULL);
    1101             :         }
    1102          23 :         wpa_s->scan_interval = sec;
    1103          23 : }
    1104             : 
    1105             : 
    1106             : /**
    1107             :  * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
    1108             :  * @wpa_s: Pointer to wpa_supplicant data
    1109             :  * @sec: Number of seconds after which to scan
    1110             :  * @usec: Number of microseconds after which to scan
    1111             :  *
    1112             :  * This function is used to schedule a scan for neighboring access points after
    1113             :  * the specified time.
    1114             :  */
    1115        6769 : void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
    1116             : {
    1117             :         int res;
    1118             : 
    1119        6769 :         if (wpa_s->p2p_mgmt) {
    1120           2 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    1121             :                         "Ignore scan request (%d.%06d sec) on p2p_mgmt interface",
    1122             :                         sec, usec);
    1123        6771 :                 return;
    1124             :         }
    1125             : 
    1126        6767 :         res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
    1127             :                                     NULL);
    1128        6767 :         if (res == 1) {
    1129         152 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d.%06d sec",
    1130             :                         sec, usec);
    1131        6615 :         } else if (res == 0) {
    1132         425 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner",
    1133             :                         sec, usec);
    1134             :         } else {
    1135        6190 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d.%06d sec",
    1136             :                         sec, usec);
    1137        6190 :                 eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
    1138             :         }
    1139             : }
    1140             : 
    1141             : 
    1142             : /**
    1143             :  * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan
    1144             :  * @wpa_s: Pointer to wpa_supplicant data
    1145             :  * @sec: Number of seconds after which to scan
    1146             :  * @usec: Number of microseconds after which to scan
    1147             :  * Returns: 0 on success or -1 otherwise
    1148             :  *
    1149             :  * This function is used to schedule periodic scans for neighboring
    1150             :  * access points after the specified time.
    1151             :  */
    1152           0 : int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
    1153             :                                       int sec, int usec)
    1154             : {
    1155           0 :         if (!wpa_s->sched_scan_supported)
    1156           0 :                 return -1;
    1157             : 
    1158           0 :         eloop_register_timeout(sec, usec,
    1159             :                                wpa_supplicant_delayed_sched_scan_timeout,
    1160             :                                wpa_s, NULL);
    1161             : 
    1162           0 :         return 0;
    1163             : }
    1164             : 
    1165             : 
    1166             : /**
    1167             :  * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
    1168             :  * @wpa_s: Pointer to wpa_supplicant data
    1169             :  * Returns: 0 is sched_scan was started or -1 otherwise
    1170             :  *
    1171             :  * This function is used to schedule periodic scans for neighboring
    1172             :  * access points repeating the scan continuously.
    1173             :  */
    1174         562 : int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
    1175             : {
    1176             :         struct wpa_driver_scan_params params;
    1177             :         struct wpa_driver_scan_params *scan_params;
    1178             :         enum wpa_states prev_state;
    1179         562 :         struct wpa_ssid *ssid = NULL;
    1180         562 :         struct wpabuf *extra_ie = NULL;
    1181             :         int ret;
    1182             :         unsigned int max_sched_scan_ssids;
    1183         562 :         int wildcard = 0;
    1184             :         int need_ssids;
    1185             : 
    1186         562 :         if (!wpa_s->sched_scan_supported)
    1187         562 :                 return -1;
    1188             : 
    1189           0 :         if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
    1190           0 :                 max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
    1191             :         else
    1192           0 :                 max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
    1193           0 :         if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
    1194           0 :                 return -1;
    1195             : 
    1196           0 :         if (wpa_s->sched_scanning) {
    1197           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
    1198           0 :                 return 0;
    1199             :         }
    1200             : 
    1201           0 :         need_ssids = 0;
    1202           0 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    1203           0 :                 if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) {
    1204             :                         /* Use wildcard SSID to find this network */
    1205           0 :                         wildcard = 1;
    1206           0 :                 } else if (!wpas_network_disabled(wpa_s, ssid) &&
    1207           0 :                            ssid->ssid_len)
    1208           0 :                         need_ssids++;
    1209             : 
    1210             : #ifdef CONFIG_WPS
    1211           0 :                 if (!wpas_network_disabled(wpa_s, ssid) &&
    1212           0 :                     ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
    1213             :                         /*
    1214             :                          * Normal scan is more reliable and faster for WPS
    1215             :                          * operations and since these are for short periods of
    1216             :                          * time, the benefit of trying to use sched_scan would
    1217             :                          * be limited.
    1218             :                          */
    1219           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
    1220             :                                 "sched_scan for WPS");
    1221           0 :                         return -1;
    1222             :                 }
    1223             : #endif /* CONFIG_WPS */
    1224             :         }
    1225           0 :         if (wildcard)
    1226           0 :                 need_ssids++;
    1227             : 
    1228           0 :         if (wpa_s->normal_scans < 3 &&
    1229           0 :             (need_ssids <= wpa_s->max_scan_ssids ||
    1230           0 :              wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) {
    1231             :                 /*
    1232             :                  * When normal scan can speed up operations, use that for the
    1233             :                  * first operations before starting the sched_scan to allow
    1234             :                  * user space sleep more. We do this only if the normal scan
    1235             :                  * has functionality that is suitable for this or if the
    1236             :                  * sched_scan does not have better support for multiple SSIDs.
    1237             :                  */
    1238           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of "
    1239             :                         "sched_scan for initial scans (normal_scans=%d)",
    1240             :                         wpa_s->normal_scans);
    1241           0 :                 return -1;
    1242             :         }
    1243             : 
    1244           0 :         os_memset(&params, 0, sizeof(params));
    1245             : 
    1246             :         /* If we can't allocate space for the filters, we just don't filter */
    1247           0 :         params.filter_ssids = os_calloc(wpa_s->max_match_sets,
    1248             :                                         sizeof(struct wpa_driver_scan_filter));
    1249             : 
    1250           0 :         prev_state = wpa_s->wpa_state;
    1251           0 :         if (wpa_s->wpa_state == WPA_DISCONNECTED ||
    1252           0 :             wpa_s->wpa_state == WPA_INACTIVE)
    1253           0 :                 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
    1254             : 
    1255           0 :         if (wpa_s->autoscan_params != NULL) {
    1256           0 :                 scan_params = wpa_s->autoscan_params;
    1257           0 :                 goto scan;
    1258             :         }
    1259             : 
    1260             :         /* Find the starting point from which to continue scanning */
    1261           0 :         ssid = wpa_s->conf->ssid;
    1262           0 :         if (wpa_s->prev_sched_ssid) {
    1263           0 :                 while (ssid) {
    1264           0 :                         if (ssid == wpa_s->prev_sched_ssid) {
    1265           0 :                                 ssid = ssid->next;
    1266           0 :                                 break;
    1267             :                         }
    1268           0 :                         ssid = ssid->next;
    1269             :                 }
    1270             :         }
    1271             : 
    1272           0 :         if (!ssid || !wpa_s->prev_sched_ssid) {
    1273           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
    1274           0 :                 if (wpa_s->conf->sched_scan_interval)
    1275           0 :                         wpa_s->sched_scan_interval =
    1276           0 :                                 wpa_s->conf->sched_scan_interval;
    1277           0 :                 if (wpa_s->sched_scan_interval == 0)
    1278           0 :                         wpa_s->sched_scan_interval = 10;
    1279           0 :                 wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
    1280           0 :                 wpa_s->first_sched_scan = 1;
    1281           0 :                 ssid = wpa_s->conf->ssid;
    1282           0 :                 wpa_s->prev_sched_ssid = ssid;
    1283             :         }
    1284             : 
    1285           0 :         if (wildcard) {
    1286           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan");
    1287           0 :                 params.num_ssids++;
    1288             :         }
    1289             : 
    1290           0 :         while (ssid) {
    1291           0 :                 if (wpas_network_disabled(wpa_s, ssid))
    1292           0 :                         goto next;
    1293             : 
    1294           0 :                 if (params.num_filter_ssids < wpa_s->max_match_sets &&
    1295           0 :                     params.filter_ssids && ssid->ssid && ssid->ssid_len) {
    1296           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s",
    1297             :                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
    1298           0 :                         os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid,
    1299             :                                   ssid->ssid, ssid->ssid_len);
    1300           0 :                         params.filter_ssids[params.num_filter_ssids].ssid_len =
    1301           0 :                                 ssid->ssid_len;
    1302           0 :                         params.num_filter_ssids++;
    1303           0 :                 } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len)
    1304             :                 {
    1305           0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID "
    1306             :                                 "filter for sched_scan - drop filter");
    1307           0 :                         os_free(params.filter_ssids);
    1308           0 :                         params.filter_ssids = NULL;
    1309           0 :                         params.num_filter_ssids = 0;
    1310             :                 }
    1311             : 
    1312           0 :                 if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) {
    1313           0 :                         if (params.num_ssids == max_sched_scan_ssids)
    1314           0 :                                 break; /* only room for broadcast SSID */
    1315           0 :                         wpa_dbg(wpa_s, MSG_DEBUG,
    1316             :                                 "add to active scan ssid: %s",
    1317             :                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
    1318           0 :                         params.ssids[params.num_ssids].ssid =
    1319           0 :                                 ssid->ssid;
    1320           0 :                         params.ssids[params.num_ssids].ssid_len =
    1321           0 :                                 ssid->ssid_len;
    1322           0 :                         params.num_ssids++;
    1323           0 :                         if (params.num_ssids >= max_sched_scan_ssids) {
    1324           0 :                                 wpa_s->prev_sched_ssid = ssid;
    1325             :                                 do {
    1326           0 :                                         ssid = ssid->next;
    1327           0 :                                 } while (ssid &&
    1328           0 :                                          (wpas_network_disabled(wpa_s, ssid) ||
    1329           0 :                                           !ssid->scan_ssid));
    1330           0 :                                 break;
    1331             :                         }
    1332             :                 }
    1333             : 
    1334             :         next:
    1335           0 :                 wpa_s->prev_sched_ssid = ssid;
    1336           0 :                 ssid = ssid->next;
    1337             :         }
    1338             : 
    1339           0 :         if (params.num_filter_ssids == 0) {
    1340           0 :                 os_free(params.filter_ssids);
    1341           0 :                 params.filter_ssids = NULL;
    1342             :         }
    1343             : 
    1344           0 :         extra_ie = wpa_supplicant_extra_ies(wpa_s);
    1345           0 :         if (extra_ie) {
    1346           0 :                 params.extra_ies = wpabuf_head(extra_ie);
    1347           0 :                 params.extra_ies_len = wpabuf_len(extra_ie);
    1348             :         }
    1349             : 
    1350           0 :         if (wpa_s->conf->filter_rssi)
    1351           0 :                 params.filter_rssi = wpa_s->conf->filter_rssi;
    1352             : 
    1353             :         /* See if user specified frequencies. If so, scan only those. */
    1354           0 :         if (wpa_s->conf->freq_list && !params.freqs) {
    1355           0 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    1356             :                         "Optimize scan based on conf->freq_list");
    1357           0 :                 int_array_concat(&params.freqs, wpa_s->conf->freq_list);
    1358             :         }
    1359             : 
    1360           0 :         scan_params = &params;
    1361             : 
    1362             : scan:
    1363           0 :         if (ssid || !wpa_s->first_sched_scan) {
    1364           0 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    1365             :                         "Starting sched scan: interval %d timeout %d",
    1366             :                         wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout);
    1367             :         } else {
    1368           0 :                 wpa_dbg(wpa_s, MSG_DEBUG,
    1369             :                         "Starting sched scan: interval %d (no timeout)",
    1370             :                         wpa_s->sched_scan_interval);
    1371             :         }
    1372             : 
    1373           0 :         wpa_setband_scan_freqs(wpa_s, scan_params);
    1374             : 
    1375           0 :         if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) {
    1376           0 :                 params.mac_addr_rand = 1;
    1377           0 :                 if (wpa_s->mac_addr_sched_scan) {
    1378           0 :                         params.mac_addr = wpa_s->mac_addr_sched_scan;
    1379           0 :                         params.mac_addr_mask = wpa_s->mac_addr_sched_scan +
    1380             :                                 ETH_ALEN;
    1381             :                 }
    1382             :         }
    1383             : 
    1384           0 :         ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
    1385             :                                               wpa_s->sched_scan_interval);
    1386           0 :         wpabuf_free(extra_ie);
    1387           0 :         os_free(params.filter_ssids);
    1388           0 :         if (ret) {
    1389           0 :                 wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan");
    1390           0 :                 if (prev_state != wpa_s->wpa_state)
    1391           0 :                         wpa_supplicant_set_state(wpa_s, prev_state);
    1392           0 :                 return ret;
    1393             :         }
    1394             : 
    1395             :         /* If we have more SSIDs to scan, add a timeout so we scan them too */
    1396           0 :         if (ssid || !wpa_s->first_sched_scan) {
    1397           0 :                 wpa_s->sched_scan_timed_out = 0;
    1398           0 :                 eloop_register_timeout(wpa_s->sched_scan_timeout, 0,
    1399             :                                        wpa_supplicant_sched_scan_timeout,
    1400             :                                        wpa_s, NULL);
    1401           0 :                 wpa_s->first_sched_scan = 0;
    1402           0 :                 wpa_s->sched_scan_timeout /= 2;
    1403           0 :                 wpa_s->sched_scan_interval *= 2;
    1404           0 :                 if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) {
    1405           0 :                         wpa_s->sched_scan_interval = 10;
    1406           0 :                         wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
    1407             :                 }
    1408             :         }
    1409             : 
    1410             :         /* If there is no more ssids, start next time from the beginning */
    1411           0 :         if (!ssid)
    1412           0 :                 wpa_s->prev_sched_ssid = NULL;
    1413             : 
    1414           0 :         return 0;
    1415             : }
    1416             : 
    1417             : 
    1418             : /**
    1419             :  * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
    1420             :  * @wpa_s: Pointer to wpa_supplicant data
    1421             :  *
    1422             :  * This function is used to cancel a scan request scheduled with
    1423             :  * wpa_supplicant_req_scan().
    1424             :  */
    1425       10545 : void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
    1426             : {
    1427       10545 :         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
    1428       10545 :         eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
    1429       10545 : }
    1430             : 
    1431             : 
    1432             : /**
    1433             :  * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan
    1434             :  * @wpa_s: Pointer to wpa_supplicant data
    1435             :  *
    1436             :  * This function is used to stop a delayed scheduled scan.
    1437             :  */
    1438         612 : void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s)
    1439             : {
    1440         612 :         if (!wpa_s->sched_scan_supported)
    1441        1224 :                 return;
    1442             : 
    1443           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan");
    1444           0 :         eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout,
    1445             :                              wpa_s, NULL);
    1446             : }
    1447             : 
    1448             : 
    1449             : /**
    1450             :  * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans
    1451             :  * @wpa_s: Pointer to wpa_supplicant data
    1452             :  *
    1453             :  * This function is used to stop a periodic scheduled scan.
    1454             :  */
    1455        7591 : void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s)
    1456             : {
    1457        7591 :         if (!wpa_s->sched_scanning)
    1458       15182 :                 return;
    1459             : 
    1460           0 :         wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
    1461           0 :         eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
    1462           0 :         wpa_supplicant_stop_sched_scan(wpa_s);
    1463             : }
    1464             : 
    1465             : 
    1466             : /**
    1467             :  * wpa_supplicant_notify_scanning - Indicate possible scan state change
    1468             :  * @wpa_s: Pointer to wpa_supplicant data
    1469             :  * @scanning: Whether scanning is currently in progress
    1470             :  *
    1471             :  * This function is to generate scanning notifycations. It is called whenever
    1472             :  * there may have been a change in scanning (scan started, completed, stopped).
    1473             :  * wpas_notify_scanning() is called whenever the scanning state changed from the
    1474             :  * previously notified state.
    1475             :  */
    1476       36087 : void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
    1477             :                                     int scanning)
    1478             : {
    1479       36087 :         if (wpa_s->scanning != scanning) {
    1480        7434 :                 wpa_s->scanning = scanning;
    1481        7434 :                 wpas_notify_scanning(wpa_s);
    1482             :         }
    1483       36087 : }
    1484             : 
    1485             : 
    1486        5913 : static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
    1487             : {
    1488        5913 :         int rate = 0;
    1489             :         const u8 *ie;
    1490             :         int i;
    1491             : 
    1492        5913 :         ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
    1493       53201 :         for (i = 0; ie && i < ie[1]; i++) {
    1494       47288 :                 if ((ie[i + 2] & 0x7f) > rate)
    1495       39660 :                         rate = ie[i + 2] & 0x7f;
    1496             :         }
    1497             : 
    1498        5913 :         ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
    1499       21184 :         for (i = 0; ie && i < ie[1]; i++) {
    1500       15271 :                 if ((ie[i + 2] & 0x7f) > rate)
    1501       15271 :                         rate = ie[i + 2] & 0x7f;
    1502             :         }
    1503             : 
    1504        5913 :         return rate;
    1505             : }
    1506             : 
    1507             : 
    1508             : /**
    1509             :  * wpa_scan_get_ie - Fetch a specified information element from a scan result
    1510             :  * @res: Scan result entry
    1511             :  * @ie: Information element identitifier (WLAN_EID_*)
    1512             :  * Returns: Pointer to the information element (id field) or %NULL if not found
    1513             :  *
    1514             :  * This function returns the first matching information element in the scan
    1515             :  * result.
    1516             :  */
    1517       43676 : const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
    1518             : {
    1519             :         const u8 *end, *pos;
    1520             : 
    1521       43676 :         pos = (const u8 *) (res + 1);
    1522       43676 :         end = pos + res->ie_len;
    1523             : 
    1524      319487 :         while (pos + 1 < end) {
    1525      258606 :                 if (pos + 2 + pos[1] > end)
    1526           0 :                         break;
    1527      258606 :                 if (pos[0] == ie)
    1528       26471 :                         return pos;
    1529      232135 :                 pos += 2 + pos[1];
    1530             :         }
    1531             : 
    1532       17205 :         return NULL;
    1533             : }
    1534             : 
    1535             : 
    1536             : /**
    1537             :  * wpa_scan_get_vendor_ie - Fetch vendor information element from a scan result
    1538             :  * @res: Scan result entry
    1539             :  * @vendor_type: Vendor type (four octets starting the IE payload)
    1540             :  * Returns: Pointer to the information element (id field) or %NULL if not found
    1541             :  *
    1542             :  * This function returns the first matching information element in the scan
    1543             :  * result.
    1544             :  */
    1545       13001 : const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
    1546             :                                   u32 vendor_type)
    1547             : {
    1548             :         const u8 *end, *pos;
    1549             : 
    1550       13001 :         pos = (const u8 *) (res + 1);
    1551       13001 :         end = pos + res->ie_len;
    1552             : 
    1553      143457 :         while (pos + 1 < end) {
    1554      121080 :                 if (pos + 2 + pos[1] > end)
    1555           0 :                         break;
    1556      143414 :                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    1557       22334 :                     vendor_type == WPA_GET_BE32(&pos[2]))
    1558        3625 :                         return pos;
    1559      117455 :                 pos += 2 + pos[1];
    1560             :         }
    1561             : 
    1562        9376 :         return NULL;
    1563             : }
    1564             : 
    1565             : 
    1566             : /**
    1567             :  * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result
    1568             :  * @res: Scan result entry
    1569             :  * @vendor_type: Vendor type (four octets starting the IE payload)
    1570             :  * Returns: Pointer to the information element (id field) or %NULL if not found
    1571             :  *
    1572             :  * This function returns the first matching information element in the scan
    1573             :  * result.
    1574             :  *
    1575             :  * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only
    1576             :  * from Beacon frames instead of either Beacon or Probe Response frames.
    1577             :  */
    1578         323 : const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res,
    1579             :                                          u32 vendor_type)
    1580             : {
    1581             :         const u8 *end, *pos;
    1582             : 
    1583         323 :         if (res->beacon_ie_len == 0)
    1584           0 :                 return NULL;
    1585             : 
    1586         323 :         pos = (const u8 *) (res + 1);
    1587         323 :         pos += res->ie_len;
    1588         323 :         end = pos + res->beacon_ie_len;
    1589             : 
    1590        4051 :         while (pos + 1 < end) {
    1591        3415 :                 if (pos + 2 + pos[1] > end)
    1592           0 :                         break;
    1593        3806 :                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    1594         391 :                     vendor_type == WPA_GET_BE32(&pos[2]))
    1595          10 :                         return pos;
    1596        3405 :                 pos += 2 + pos[1];
    1597             :         }
    1598             : 
    1599         313 :         return NULL;
    1600             : }
    1601             : 
    1602             : 
    1603             : /**
    1604             :  * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result
    1605             :  * @res: Scan result entry
    1606             :  * @vendor_type: Vendor type (four octets starting the IE payload)
    1607             :  * Returns: Pointer to the information element payload or %NULL if not found
    1608             :  *
    1609             :  * This function returns concatenated payload of possibly fragmented vendor
    1610             :  * specific information elements in the scan result. The caller is responsible
    1611             :  * for freeing the returned buffer.
    1612             :  */
    1613        1186 : struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
    1614             :                                              u32 vendor_type)
    1615             : {
    1616             :         struct wpabuf *buf;
    1617             :         const u8 *end, *pos;
    1618             : 
    1619        1186 :         buf = wpabuf_alloc(res->ie_len);
    1620        1186 :         if (buf == NULL)
    1621           0 :                 return NULL;
    1622             : 
    1623        1186 :         pos = (const u8 *) (res + 1);
    1624        1186 :         end = pos + res->ie_len;
    1625             : 
    1626       14721 :         while (pos + 1 < end) {
    1627       12349 :                 if (pos + 2 + pos[1] > end)
    1628           0 :                         break;
    1629       15213 :                 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
    1630        2864 :                     vendor_type == WPA_GET_BE32(&pos[2]))
    1631        1163 :                         wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
    1632       12349 :                 pos += 2 + pos[1];
    1633             :         }
    1634             : 
    1635        1186 :         if (wpabuf_len(buf) == 0) {
    1636          26 :                 wpabuf_free(buf);
    1637          26 :                 buf = NULL;
    1638             :         }
    1639             : 
    1640        1186 :         return buf;
    1641             : }
    1642             : 
    1643             : 
    1644             : /*
    1645             :  * Channels with a great SNR can operate at full rate. What is a great SNR?
    1646             :  * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
    1647             :  * rule of thumb is that any SNR above 20 is good." This one
    1648             :  * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
    1649             :  * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
    1650             :  * conservative value.
    1651             :  */
    1652             : #define GREAT_SNR 30
    1653             : 
    1654             : #define IS_5GHZ(n) (n > 4000)
    1655             : 
    1656             : /* Compare function for sorting scan results. Return >0 if @b is considered
    1657             :  * better. */
    1658        1565 : static int wpa_scan_result_compar(const void *a, const void *b)
    1659             : {
    1660             : #define MIN(a,b) a < b ? a : b
    1661        1565 :         struct wpa_scan_res **_wa = (void *) a;
    1662        1565 :         struct wpa_scan_res **_wb = (void *) b;
    1663        1565 :         struct wpa_scan_res *wa = *_wa;
    1664        1565 :         struct wpa_scan_res *wb = *_wb;
    1665             :         int wpa_a, wpa_b;
    1666             :         int snr_a, snr_b, snr_a_full, snr_b_full;
    1667             : 
    1668             :         /* WPA/WPA2 support preferred */
    1669        3094 :         wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
    1670        1529 :                 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
    1671        3118 :         wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
    1672        1553 :                 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
    1673             : 
    1674        1565 :         if (wpa_b && !wpa_a)
    1675         162 :                 return 1;
    1676        1403 :         if (!wpa_b && wpa_a)
    1677         306 :                 return -1;
    1678             : 
    1679             :         /* privacy support preferred */
    1680        1560 :         if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
    1681         463 :             (wb->caps & IEEE80211_CAP_PRIVACY))
    1682         123 :                 return 1;
    1683        1608 :         if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
    1684         634 :             (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
    1685          22 :                 return -1;
    1686             : 
    1687         952 :         if (wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) {
    1688         952 :                 snr_a_full = wa->snr;
    1689         952 :                 snr_a = MIN(wa->snr, GREAT_SNR);
    1690         952 :                 snr_b_full = wb->snr;
    1691         952 :                 snr_b = MIN(wb->snr, GREAT_SNR);
    1692             :         } else {
    1693             :                 /* Level is not in dBm, so we can't calculate
    1694             :                  * SNR. Just use raw level (units unknown). */
    1695           0 :                 snr_a = snr_a_full = wa->level;
    1696           0 :                 snr_b = snr_b_full = wb->level;
    1697             :         }
    1698             : 
    1699             :         /* if SNR is close, decide by max rate or frequency band */
    1700         952 :         if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
    1701           0 :             (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
    1702         952 :                 if (wa->est_throughput != wb->est_throughput)
    1703          18 :                         return wb->est_throughput - wa->est_throughput;
    1704         934 :                 if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
    1705          80 :                         return IS_5GHZ(wa->freq) ? -1 : 1;
    1706             :         }
    1707             : 
    1708             :         /* all things being equal, use SNR; if SNRs are
    1709             :          * identical, use quality values since some drivers may only report
    1710             :          * that value and leave the signal level zero */
    1711         854 :         if (snr_b_full == snr_a_full)
    1712         542 :                 return wb->qual - wa->qual;
    1713         312 :         return snr_b_full - snr_a_full;
    1714             : #undef MIN
    1715             : }
    1716             : 
    1717             : 
    1718             : #ifdef CONFIG_WPS
    1719             : /* Compare function for sorting scan results when searching a WPS AP for
    1720             :  * provisioning. Return >0 if @b is considered better. */
    1721         143 : static int wpa_scan_result_wps_compar(const void *a, const void *b)
    1722             : {
    1723         143 :         struct wpa_scan_res **_wa = (void *) a;
    1724         143 :         struct wpa_scan_res **_wb = (void *) b;
    1725         143 :         struct wpa_scan_res *wa = *_wa;
    1726         143 :         struct wpa_scan_res *wb = *_wb;
    1727             :         int uses_wps_a, uses_wps_b;
    1728             :         struct wpabuf *wps_a, *wps_b;
    1729             :         int res;
    1730             : 
    1731             :         /* Optimization - check WPS IE existence before allocated memory and
    1732             :          * doing full reassembly. */
    1733         143 :         uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
    1734         143 :         uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
    1735         143 :         if (uses_wps_a && !uses_wps_b)
    1736           6 :                 return -1;
    1737         137 :         if (!uses_wps_a && uses_wps_b)
    1738          27 :                 return 1;
    1739             : 
    1740         110 :         if (uses_wps_a && uses_wps_b) {
    1741         108 :                 wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
    1742         108 :                 wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
    1743         108 :                 res = wps_ap_priority_compar(wps_a, wps_b);
    1744         108 :                 wpabuf_free(wps_a);
    1745         108 :                 wpabuf_free(wps_b);
    1746         108 :                 if (res)
    1747          48 :                         return res;
    1748             :         }
    1749             : 
    1750             :         /*
    1751             :          * Do not use current AP security policy as a sorting criteria during
    1752             :          * WPS provisioning step since the AP may get reconfigured at the
    1753             :          * completion of provisioning.
    1754             :          */
    1755             : 
    1756             :         /* all things being equal, use signal level; if signal levels are
    1757             :          * identical, use quality values since some drivers may only report
    1758             :          * that value and leave the signal level zero */
    1759          62 :         if (wb->level == wa->level)
    1760          61 :                 return wb->qual - wa->qual;
    1761           1 :         return wb->level - wa->level;
    1762             : }
    1763             : #endif /* CONFIG_WPS */
    1764             : 
    1765             : 
    1766        4746 : static void dump_scan_res(struct wpa_scan_results *scan_res)
    1767             : {
    1768             : #ifndef CONFIG_NO_STDOUT_DEBUG
    1769             :         size_t i;
    1770             : 
    1771        4746 :         if (scan_res->res == NULL || scan_res->num == 0)
    1772        5102 :                 return;
    1773             : 
    1774        4390 :         wpa_printf(MSG_EXCESSIVE, "Sorted scan results");
    1775             : 
    1776       10303 :         for (i = 0; i < scan_res->num; i++) {
    1777        5913 :                 struct wpa_scan_res *r = scan_res->res[i];
    1778             :                 u8 *pos;
    1779        5913 :                 if (r->flags & WPA_SCAN_LEVEL_DBM) {
    1780        5913 :                         int noise_valid = !(r->flags & WPA_SCAN_NOISE_INVALID);
    1781             : 
    1782       47304 :                         wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
    1783             :                                    "noise=%d%s level=%d snr=%d%s flags=0x%x age=%u est=%u",
    1784       35478 :                                    MAC2STR(r->bssid), r->freq, r->qual,
    1785             :                                    r->noise, noise_valid ? "" : "~", r->level,
    1786        5913 :                                    r->snr, r->snr >= GREAT_SNR ? "*" : "",
    1787             :                                    r->flags,
    1788             :                                    r->age, r->est_throughput);
    1789             :                 } else {
    1790           0 :                         wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d "
    1791             :                                    "noise=%d level=%d flags=0x%x age=%u est=%u",
    1792           0 :                                    MAC2STR(r->bssid), r->freq, r->qual,
    1793             :                                    r->noise, r->level, r->flags, r->age,
    1794             :                                    r->est_throughput);
    1795             :                 }
    1796        5913 :                 pos = (u8 *) (r + 1);
    1797        5913 :                 if (r->ie_len)
    1798        5913 :                         wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len);
    1799        5913 :                 pos += r->ie_len;
    1800        5913 :                 if (r->beacon_ie_len)
    1801        3603 :                         wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs",
    1802             :                                     pos, r->beacon_ie_len);
    1803             :         }
    1804             : #endif /* CONFIG_NO_STDOUT_DEBUG */
    1805             : }
    1806             : 
    1807             : 
    1808             : /**
    1809             :  * wpa_supplicant_filter_bssid_match - Is the specified BSSID allowed
    1810             :  * @wpa_s: Pointer to wpa_supplicant data
    1811             :  * @bssid: BSSID to check
    1812             :  * Returns: 0 if the BSSID is filtered or 1 if not
    1813             :  *
    1814             :  * This function is used to filter out specific BSSIDs from scan reslts mainly
    1815             :  * for testing purposes (SET bssid_filter ctrl_iface command).
    1816             :  */
    1817       13004 : int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s,
    1818             :                                       const u8 *bssid)
    1819             : {
    1820             :         size_t i;
    1821             : 
    1822       13004 :         if (wpa_s->bssid_filter == NULL)
    1823       12994 :                 return 1;
    1824             : 
    1825          13 :         for (i = 0; i < wpa_s->bssid_filter_count; i++) {
    1826          10 :                 if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid,
    1827             :                               ETH_ALEN) == 0)
    1828           7 :                         return 1;
    1829             :         }
    1830             : 
    1831           3 :         return 0;
    1832             : }
    1833             : 
    1834             : 
    1835        4746 : static void filter_scan_res(struct wpa_supplicant *wpa_s,
    1836             :                             struct wpa_scan_results *res)
    1837             : {
    1838             :         size_t i, j;
    1839             : 
    1840        4746 :         if (wpa_s->bssid_filter == NULL)
    1841        9490 :                 return;
    1842             : 
    1843           6 :         for (i = 0, j = 0; i < res->num; i++) {
    1844           4 :                 if (wpa_supplicant_filter_bssid_match(wpa_s,
    1845           4 :                                                       res->res[i]->bssid)) {
    1846           2 :                         res->res[j++] = res->res[i];
    1847             :                 } else {
    1848           2 :                         os_free(res->res[i]);
    1849           2 :                         res->res[i] = NULL;
    1850             :                 }
    1851             :         }
    1852             : 
    1853           2 :         if (res->num != j) {
    1854           2 :                 wpa_printf(MSG_DEBUG, "Filtered out %d scan results",
    1855           2 :                            (int) (res->num - j));
    1856           2 :                 res->num = j;
    1857             :         }
    1858             : }
    1859             : 
    1860             : 
    1861             : /*
    1862             :  * Noise floor values to use when we have signal strength
    1863             :  * measurements, but no noise floor measurments. These values were
    1864             :  * measured in an office environment with many APs.
    1865             :  */
    1866             : #define DEFAULT_NOISE_FLOOR_2GHZ (-89)
    1867             : #define DEFAULT_NOISE_FLOOR_5GHZ (-92)
    1868             : 
    1869        5913 : static void scan_snr(struct wpa_scan_res *res)
    1870             : {
    1871        5913 :         if (res->flags & WPA_SCAN_NOISE_INVALID) {
    1872        2812 :                 res->noise = IS_5GHZ(res->freq) ?
    1873        1406 :                         DEFAULT_NOISE_FLOOR_5GHZ :
    1874             :                         DEFAULT_NOISE_FLOOR_2GHZ;
    1875             :         }
    1876             : 
    1877        5913 :         if (res->flags & WPA_SCAN_LEVEL_DBM) {
    1878        5913 :                 res->snr = res->level - res->noise;
    1879             :         } else {
    1880             :                 /* Level is not in dBm, so we can't calculate
    1881             :                  * SNR. Just use raw level (units unknown). */
    1882           0 :                 res->snr = res->level;
    1883             :         }
    1884        5913 : }
    1885             : 
    1886             : 
    1887        4722 : static unsigned int max_ht20_rate(int snr)
    1888             : {
    1889        4722 :         if (snr < 6)
    1890           0 :                 return 6500; /* HT20 MCS0 */
    1891        4722 :         if (snr < 8)
    1892           0 :                 return 13000; /* HT20 MCS1 */
    1893        4722 :         if (snr < 13)
    1894           0 :                 return 19500; /* HT20 MCS2 */
    1895        4722 :         if (snr < 17)
    1896           0 :                 return 26000; /* HT20 MCS3 */
    1897        4722 :         if (snr < 20)
    1898           0 :                 return 39000; /* HT20 MCS4 */
    1899        4722 :         if (snr < 23)
    1900           0 :                 return 52000; /* HT20 MCS5 */
    1901        4722 :         if (snr < 24)
    1902           0 :                 return 58500; /* HT20 MCS6 */
    1903        4722 :         return 65000; /* HT20 MCS7 */
    1904             : }
    1905             : 
    1906             : 
    1907          80 : static unsigned int max_ht40_rate(int snr)
    1908             : {
    1909          80 :         if (snr < 3)
    1910           0 :                 return 13500; /* HT40 MCS0 */
    1911          80 :         if (snr < 6)
    1912           0 :                 return 27000; /* HT40 MCS1 */
    1913          80 :         if (snr < 10)
    1914           0 :                 return 40500; /* HT40 MCS2 */
    1915          80 :         if (snr < 15)
    1916           0 :                 return 54000; /* HT40 MCS3 */
    1917          80 :         if (snr < 17)
    1918           0 :                 return 81000; /* HT40 MCS4 */
    1919          80 :         if (snr < 22)
    1920           0 :                 return 108000; /* HT40 MCS5 */
    1921          80 :         if (snr < 24)
    1922           0 :                 return 121500; /* HT40 MCS6 */
    1923          80 :         return 135000; /* HT40 MCS7 */
    1924             : }
    1925             : 
    1926             : 
    1927          14 : static unsigned int max_vht80_rate(int snr)
    1928             : {
    1929          14 :         if (snr < 1)
    1930           0 :                 return 0;
    1931          14 :         if (snr < 2)
    1932           0 :                 return 29300; /* VHT80 MCS0 */
    1933          14 :         if (snr < 5)
    1934           0 :                 return 58500; /* VHT80 MCS1 */
    1935          14 :         if (snr < 9)
    1936           0 :                 return 87800; /* VHT80 MCS2 */
    1937          14 :         if (snr < 11)
    1938           0 :                 return 117000; /* VHT80 MCS3 */
    1939          14 :         if (snr < 15)
    1940           0 :                 return 175500; /* VHT80 MCS4 */
    1941          14 :         if (snr < 16)
    1942           0 :                 return 234000; /* VHT80 MCS5 */
    1943          14 :         if (snr < 18)
    1944           0 :                 return 263300; /* VHT80 MCS6 */
    1945          14 :         if (snr < 20)
    1946           0 :                 return 292500; /* VHT80 MCS7 */
    1947          14 :         if (snr < 22)
    1948           0 :                 return 351000; /* VHT80 MCS8 */
    1949          14 :         return 390000; /* VHT80 MCS9 */
    1950             : }
    1951             : 
    1952             : 
    1953        5913 : static void scan_est_throughput(struct wpa_supplicant *wpa_s,
    1954             :                                 struct wpa_scan_res *res)
    1955             : {
    1956        5913 :         enum local_hw_capab capab = wpa_s->hw_capab;
    1957             :         int rate; /* max legacy rate in 500 kb/s units */
    1958             :         const u8 *ie;
    1959             :         unsigned int est, tmp;
    1960        5913 :         int snr = res->snr;
    1961             : 
    1962        5913 :         if (res->est_throughput)
    1963        5913 :                 return;
    1964             : 
    1965             :         /* Get maximum legacy rate */
    1966        5913 :         rate = wpa_scan_get_max_rate(res);
    1967             : 
    1968             :         /* Limit based on estimated SNR */
    1969        5913 :         if (rate > 1 * 2 && snr < 1)
    1970           0 :                 rate = 1 * 2;
    1971        5913 :         else if (rate > 2 * 2 && snr < 4)
    1972           0 :                 rate = 2 * 2;
    1973        5913 :         else if (rate > 6 * 2 && snr < 5)
    1974           0 :                 rate = 6 * 2;
    1975        5913 :         else if (rate > 9 * 2 && snr < 6)
    1976           0 :                 rate = 9 * 2;
    1977        5913 :         else if (rate > 12 * 2 && snr < 7)
    1978           0 :                 rate = 12 * 2;
    1979        5913 :         else if (rate > 18 * 2 && snr < 10)
    1980           0 :                 rate = 18 * 2;
    1981        5913 :         else if (rate > 24 * 2 && snr < 11)
    1982           0 :                 rate = 24 * 2;
    1983        5913 :         else if (rate > 36 * 2 && snr < 15)
    1984           0 :                 rate = 36 * 2;
    1985        5913 :         else if (rate > 48 * 2 && snr < 19)
    1986           0 :                 rate = 48 * 2;
    1987        5913 :         else if (rate > 54 * 2 && snr < 21)
    1988           0 :                 rate = 54 * 2;
    1989        5913 :         est = rate * 500;
    1990             : 
    1991        5913 :         if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) {
    1992        5884 :                 ie = wpa_scan_get_ie(res, WLAN_EID_HT_CAP);
    1993        5884 :                 if (ie) {
    1994        4702 :                         tmp = max_ht20_rate(snr);
    1995        4702 :                         if (tmp > est)
    1996        4702 :                                 est = tmp;
    1997             :                 }
    1998             :         }
    1999             : 
    2000        5913 :         if (capab == CAPAB_HT40 || capab == CAPAB_VHT) {
    2001        5884 :                 ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION);
    2002       10586 :                 if (ie && ie[1] >= 2 &&
    2003        4702 :                     (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
    2004          64 :                         tmp = max_ht40_rate(snr);
    2005          64 :                         if (tmp > est)
    2006          64 :                                 est = tmp;
    2007             :                 }
    2008             :         }
    2009             : 
    2010        5913 :         if (capab == CAPAB_VHT) {
    2011             :                 /* Use +1 to assume VHT is always faster than HT */
    2012        5884 :                 ie = wpa_scan_get_ie(res, WLAN_EID_VHT_CAP);
    2013        5884 :                 if (ie) {
    2014          20 :                         tmp = max_ht20_rate(snr) + 1;
    2015          20 :                         if (tmp > est)
    2016           4 :                                 est = tmp;
    2017             : 
    2018          20 :                         ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION);
    2019          40 :                         if (ie && ie[1] >= 2 &&
    2020          20 :                             (ie[3] &
    2021             :                              HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
    2022          16 :                                 tmp = max_ht40_rate(snr) + 1;
    2023          16 :                                 if (tmp > est)
    2024          16 :                                         est = tmp;
    2025             :                         }
    2026             : 
    2027          20 :                         ie = wpa_scan_get_ie(res, WLAN_EID_VHT_OPERATION);
    2028          40 :                         if (ie && ie[1] >= 1 &&
    2029          20 :                             (ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK)) {
    2030          14 :                                 tmp = max_vht80_rate(snr) + 1;
    2031          14 :                                 if (tmp > est)
    2032          14 :                                         est = tmp;
    2033             :                         }
    2034             :                 }
    2035             :         }
    2036             : 
    2037             :         /* TODO: channel utilization and AP load (e.g., from AP Beacon) */
    2038             : 
    2039        5913 :         res->est_throughput = est;
    2040             : }
    2041             : 
    2042             : 
    2043             : /**
    2044             :  * wpa_supplicant_get_scan_results - Get scan results
    2045             :  * @wpa_s: Pointer to wpa_supplicant data
    2046             :  * @info: Information about what was scanned or %NULL if not available
    2047             :  * @new_scan: Whether a new scan was performed
    2048             :  * Returns: Scan results, %NULL on failure
    2049             :  *
    2050             :  * This function request the current scan results from the driver and updates
    2051             :  * the local BSS list wpa_s->bss. The caller is responsible for freeing the
    2052             :  * results with wpa_scan_results_free().
    2053             :  */
    2054             : struct wpa_scan_results *
    2055        4746 : wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
    2056             :                                 struct scan_info *info, int new_scan)
    2057             : {
    2058             :         struct wpa_scan_results *scan_res;
    2059             :         size_t i;
    2060        4746 :         int (*compar)(const void *, const void *) = wpa_scan_result_compar;
    2061             : 
    2062        4746 :         scan_res = wpa_drv_get_scan_results2(wpa_s);
    2063        4746 :         if (scan_res == NULL) {
    2064           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
    2065           0 :                 return NULL;
    2066             :         }
    2067        4746 :         if (scan_res->fetch_time.sec == 0) {
    2068             :                 /*
    2069             :                  * Make sure we have a valid timestamp if the driver wrapper
    2070             :                  * does not set this.
    2071             :                  */
    2072        4746 :                 os_get_reltime(&scan_res->fetch_time);
    2073             :         }
    2074        4746 :         filter_scan_res(wpa_s, scan_res);
    2075             : 
    2076       10659 :         for (i = 0; i < scan_res->num; i++) {
    2077        5913 :                 struct wpa_scan_res *scan_res_item = scan_res->res[i];
    2078             : 
    2079        5913 :                 scan_snr(scan_res_item);
    2080        5913 :                 scan_est_throughput(wpa_s, scan_res_item);
    2081             :         }
    2082             : 
    2083             : #ifdef CONFIG_WPS
    2084        4746 :         if (wpas_wps_searching(wpa_s)) {
    2085         616 :                 wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
    2086             :                         "provisioning rules");
    2087         616 :                 compar = wpa_scan_result_wps_compar;
    2088             :         }
    2089             : #endif /* CONFIG_WPS */
    2090             : 
    2091        4746 :         qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
    2092             :               compar);
    2093        4746 :         dump_scan_res(scan_res);
    2094             : 
    2095        4746 :         wpa_bss_update_start(wpa_s);
    2096       10659 :         for (i = 0; i < scan_res->num; i++)
    2097        5913 :                 wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
    2098             :                                         &scan_res->fetch_time);
    2099        4746 :         wpa_bss_update_end(wpa_s, info, new_scan);
    2100             : 
    2101        4746 :         return scan_res;
    2102             : }
    2103             : 
    2104             : 
    2105             : /**
    2106             :  * wpa_supplicant_update_scan_results - Update scan results from the driver
    2107             :  * @wpa_s: Pointer to wpa_supplicant data
    2108             :  * Returns: 0 on success, -1 on failure
    2109             :  *
    2110             :  * This function updates the BSS table within wpa_supplicant based on the
    2111             :  * currently available scan results from the driver without requesting a new
    2112             :  * scan. This is used in cases where the driver indicates an association
    2113             :  * (including roaming within ESS) and wpa_supplicant does not yet have the
    2114             :  * needed information to complete the connection (e.g., to perform validation
    2115             :  * steps in 4-way handshake).
    2116             :  */
    2117          18 : int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
    2118             : {
    2119             :         struct wpa_scan_results *scan_res;
    2120          18 :         scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
    2121          18 :         if (scan_res == NULL)
    2122           0 :                 return -1;
    2123          18 :         wpa_scan_results_free(scan_res);
    2124             : 
    2125          18 :         return 0;
    2126             : }
    2127             : 
    2128             : 
    2129             : /**
    2130             :  * scan_only_handler - Reports scan results
    2131             :  */
    2132        1152 : void scan_only_handler(struct wpa_supplicant *wpa_s,
    2133             :                        struct wpa_scan_results *scan_res)
    2134             : {
    2135        1152 :         wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received");
    2136        1152 :         if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
    2137           3 :             wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
    2138           3 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
    2139             :                              wpa_s->manual_scan_id);
    2140           3 :                 wpa_s->manual_scan_use_id = 0;
    2141             :         } else {
    2142        1149 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
    2143             :         }
    2144        1152 :         wpas_notify_scan_results(wpa_s);
    2145        1152 :         wpas_notify_scan_done(wpa_s, 1);
    2146        1152 :         if (wpa_s->scan_work) {
    2147        1152 :                 struct wpa_radio_work *work = wpa_s->scan_work;
    2148        1152 :                 wpa_s->scan_work = NULL;
    2149        1152 :                 radio_work_done(work);
    2150             :         }
    2151        1152 : }
    2152             : 
    2153             : 
    2154           0 : int wpas_scan_scheduled(struct wpa_supplicant *wpa_s)
    2155             : {
    2156           0 :         return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL);
    2157             : }
    2158             : 
    2159             : 
    2160             : struct wpa_driver_scan_params *
    2161        3718 : wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
    2162             : {
    2163             :         struct wpa_driver_scan_params *params;
    2164             :         size_t i;
    2165             :         u8 *n;
    2166             : 
    2167        3718 :         params = os_zalloc(sizeof(*params));
    2168        3718 :         if (params == NULL)
    2169           1 :                 return NULL;
    2170             : 
    2171        7419 :         for (i = 0; i < src->num_ssids; i++) {
    2172        3702 :                 if (src->ssids[i].ssid) {
    2173         290 :                         n = os_malloc(src->ssids[i].ssid_len);
    2174         290 :                         if (n == NULL)
    2175           0 :                                 goto failed;
    2176         290 :                         os_memcpy(n, src->ssids[i].ssid,
    2177             :                                   src->ssids[i].ssid_len);
    2178         290 :                         params->ssids[i].ssid = n;
    2179         290 :                         params->ssids[i].ssid_len = src->ssids[i].ssid_len;
    2180             :                 }
    2181             :         }
    2182        3717 :         params->num_ssids = src->num_ssids;
    2183             : 
    2184        3717 :         if (src->extra_ies) {
    2185        3704 :                 n = os_malloc(src->extra_ies_len);
    2186        3704 :                 if (n == NULL)
    2187           0 :                         goto failed;
    2188        3704 :                 os_memcpy(n, src->extra_ies, src->extra_ies_len);
    2189        3704 :                 params->extra_ies = n;
    2190        3704 :                 params->extra_ies_len = src->extra_ies_len;
    2191             :         }
    2192             : 
    2193        3717 :         if (src->freqs) {
    2194        3506 :                 int len = int_array_len(src->freqs);
    2195        3506 :                 params->freqs = os_malloc((len + 1) * sizeof(int));
    2196        3506 :                 if (params->freqs == NULL)
    2197           0 :                         goto failed;
    2198        3506 :                 os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int));
    2199             :         }
    2200             : 
    2201        3717 :         if (src->filter_ssids) {
    2202           2 :                 params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) *
    2203           2 :                                                  src->num_filter_ssids);
    2204           2 :                 if (params->filter_ssids == NULL)
    2205           0 :                         goto failed;
    2206           2 :                 os_memcpy(params->filter_ssids, src->filter_ssids,
    2207             :                           sizeof(*params->filter_ssids) *
    2208             :                           src->num_filter_ssids);
    2209           2 :                 params->num_filter_ssids = src->num_filter_ssids;
    2210             :         }
    2211             : 
    2212        3717 :         params->filter_rssi = src->filter_rssi;
    2213        3717 :         params->p2p_probe = src->p2p_probe;
    2214        3717 :         params->only_new_results = src->only_new_results;
    2215        3717 :         params->low_priority = src->low_priority;
    2216             : 
    2217        3717 :         if (src->mac_addr_rand) {
    2218           3 :                 params->mac_addr_rand = src->mac_addr_rand;
    2219             : 
    2220           3 :                 if (src->mac_addr && src->mac_addr_mask) {
    2221             :                         u8 *mac_addr;
    2222             : 
    2223           2 :                         mac_addr = os_malloc(2 * ETH_ALEN);
    2224           2 :                         if (!mac_addr)
    2225           0 :                                 goto failed;
    2226             : 
    2227           2 :                         os_memcpy(mac_addr, src->mac_addr, ETH_ALEN);
    2228           2 :                         os_memcpy(mac_addr + ETH_ALEN, src->mac_addr_mask,
    2229             :                                   ETH_ALEN);
    2230           2 :                         params->mac_addr = mac_addr;
    2231           2 :                         params->mac_addr_mask = mac_addr + ETH_ALEN;
    2232             :                 }
    2233             :         }
    2234        3717 :         return params;
    2235             : 
    2236             : failed:
    2237           0 :         wpa_scan_free_params(params);
    2238           0 :         return NULL;
    2239             : }
    2240             : 
    2241             : 
    2242        4620 : void wpa_scan_free_params(struct wpa_driver_scan_params *params)
    2243             : {
    2244             :         size_t i;
    2245             : 
    2246        4620 :         if (params == NULL)
    2247        4620 :                 return;
    2248             : 
    2249        9225 :         for (i = 0; i < params->num_ssids; i++)
    2250        4605 :                 os_free((u8 *) params->ssids[i].ssid);
    2251        4620 :         os_free((u8 *) params->extra_ies);
    2252        4620 :         os_free(params->freqs);
    2253        4620 :         os_free(params->filter_ssids);
    2254             : 
    2255             :         /*
    2256             :          * Note: params->mac_addr_mask points to same memory allocation and
    2257             :          * must not be freed separately.
    2258             :          */
    2259        4620 :         os_free((u8 *) params->mac_addr);
    2260             : 
    2261        4620 :         os_free(params);
    2262             : }
    2263             : 
    2264             : 
    2265           4 : int wpas_start_pno(struct wpa_supplicant *wpa_s)
    2266             : {
    2267             :         int ret, interval, prio;
    2268             :         size_t i, num_ssid, num_match_ssid;
    2269             :         struct wpa_ssid *ssid;
    2270             :         struct wpa_driver_scan_params params;
    2271             : 
    2272           4 :         if (!wpa_s->sched_scan_supported)
    2273           4 :                 return -1;
    2274             : 
    2275           0 :         if (wpa_s->pno || wpa_s->pno_sched_pending)
    2276           0 :                 return 0;
    2277             : 
    2278           0 :         if ((wpa_s->wpa_state > WPA_SCANNING) &&
    2279           0 :             (wpa_s->wpa_state <= WPA_COMPLETED)) {
    2280           0 :                 wpa_printf(MSG_ERROR, "PNO: In assoc process");
    2281           0 :                 return -EAGAIN;
    2282             :         }
    2283             : 
    2284           0 :         if (wpa_s->wpa_state == WPA_SCANNING) {
    2285           0 :                 wpa_supplicant_cancel_scan(wpa_s);
    2286           0 :                 if (wpa_s->sched_scanning) {
    2287           0 :                         wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
    2288             :                                    "ongoing sched scan");
    2289           0 :                         wpa_supplicant_cancel_sched_scan(wpa_s);
    2290           0 :                         wpa_s->pno_sched_pending = 1;
    2291           0 :                         return 0;
    2292             :                 }
    2293             :         }
    2294             : 
    2295           0 :         os_memset(&params, 0, sizeof(params));
    2296             : 
    2297           0 :         num_ssid = num_match_ssid = 0;
    2298           0 :         ssid = wpa_s->conf->ssid;
    2299           0 :         while (ssid) {
    2300           0 :                 if (!wpas_network_disabled(wpa_s, ssid)) {
    2301           0 :                         num_match_ssid++;
    2302           0 :                         if (ssid->scan_ssid)
    2303           0 :                                 num_ssid++;
    2304             :                 }
    2305           0 :                 ssid = ssid->next;
    2306             :         }
    2307             : 
    2308           0 :         if (num_match_ssid == 0) {
    2309           0 :                 wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
    2310           0 :                 return -1;
    2311             :         }
    2312             : 
    2313           0 :         if (num_match_ssid > num_ssid) {
    2314           0 :                 params.num_ssids++; /* wildcard */
    2315           0 :                 num_ssid++;
    2316             :         }
    2317             : 
    2318           0 :         if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
    2319           0 :                 wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
    2320             :                            "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
    2321           0 :                 num_ssid = WPAS_MAX_SCAN_SSIDS;
    2322             :         }
    2323             : 
    2324           0 :         if (num_match_ssid > wpa_s->max_match_sets) {
    2325           0 :                 num_match_ssid = wpa_s->max_match_sets;
    2326           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "PNO: Too many SSIDs to match");
    2327             :         }
    2328           0 :         params.filter_ssids = os_calloc(num_match_ssid,
    2329             :                                         sizeof(struct wpa_driver_scan_filter));
    2330           0 :         if (params.filter_ssids == NULL)
    2331           0 :                 return -1;
    2332             : 
    2333           0 :         i = 0;
    2334           0 :         prio = 0;
    2335           0 :         ssid = wpa_s->conf->pssid[prio];
    2336           0 :         while (ssid) {
    2337           0 :                 if (!wpas_network_disabled(wpa_s, ssid)) {
    2338           0 :                         if (ssid->scan_ssid && params.num_ssids < num_ssid) {
    2339           0 :                                 params.ssids[params.num_ssids].ssid =
    2340           0 :                                         ssid->ssid;
    2341           0 :                                 params.ssids[params.num_ssids].ssid_len =
    2342           0 :                                          ssid->ssid_len;
    2343           0 :                                 params.num_ssids++;
    2344             :                         }
    2345           0 :                         os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
    2346             :                                   ssid->ssid_len);
    2347           0 :                         params.filter_ssids[i].ssid_len = ssid->ssid_len;
    2348           0 :                         params.num_filter_ssids++;
    2349           0 :                         i++;
    2350           0 :                         if (i == num_match_ssid)
    2351           0 :                                 break;
    2352             :                 }
    2353           0 :                 if (ssid->pnext)
    2354           0 :                         ssid = ssid->pnext;
    2355           0 :                 else if (prio + 1 == wpa_s->conf->num_prio)
    2356           0 :                         break;
    2357             :                 else
    2358           0 :                         ssid = wpa_s->conf->pssid[++prio];
    2359             :         }
    2360             : 
    2361           0 :         if (wpa_s->conf->filter_rssi)
    2362           0 :                 params.filter_rssi = wpa_s->conf->filter_rssi;
    2363             : 
    2364           0 :         interval = wpa_s->conf->sched_scan_interval ?
    2365           0 :                 wpa_s->conf->sched_scan_interval : 10;
    2366             : 
    2367           0 :         if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
    2368           0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
    2369           0 :                 params.freqs = wpa_s->manual_sched_scan_freqs;
    2370             :         }
    2371             : 
    2372           0 :         if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) {
    2373           0 :                 params.mac_addr_rand = 1;
    2374           0 :                 if (wpa_s->mac_addr_pno) {
    2375           0 :                         params.mac_addr = wpa_s->mac_addr_pno;
    2376           0 :                         params.mac_addr_mask = wpa_s->mac_addr_pno + ETH_ALEN;
    2377             :                 }
    2378             :         }
    2379             : 
    2380           0 :         ret = wpa_supplicant_start_sched_scan(wpa_s, &params, interval);
    2381           0 :         os_free(params.filter_ssids);
    2382           0 :         if (ret == 0)
    2383           0 :                 wpa_s->pno = 1;
    2384             :         else
    2385           0 :                 wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
    2386           0 :         return ret;
    2387             : }
    2388             : 
    2389             : 
    2390           1 : int wpas_stop_pno(struct wpa_supplicant *wpa_s)
    2391             : {
    2392           1 :         int ret = 0;
    2393             : 
    2394           1 :         if (!wpa_s->pno)
    2395           1 :                 return 0;
    2396             : 
    2397           0 :         ret = wpa_supplicant_stop_sched_scan(wpa_s);
    2398             : 
    2399           0 :         wpa_s->pno = 0;
    2400           0 :         wpa_s->pno_sched_pending = 0;
    2401             : 
    2402           0 :         if (wpa_s->wpa_state == WPA_SCANNING)
    2403           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    2404             : 
    2405           0 :         return ret;
    2406             : }
    2407             : 
    2408             : 
    2409         616 : void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s,
    2410             :                                     unsigned int type)
    2411             : {
    2412         616 :         type &= MAC_ADDR_RAND_ALL;
    2413         616 :         wpa_s->mac_addr_rand_enable &= ~type;
    2414             : 
    2415         616 :         if (type & MAC_ADDR_RAND_SCAN) {
    2416         616 :                 os_free(wpa_s->mac_addr_scan);
    2417         616 :                 wpa_s->mac_addr_scan = NULL;
    2418             :         }
    2419             : 
    2420         616 :         if (type & MAC_ADDR_RAND_SCHED_SCAN) {
    2421         612 :                 os_free(wpa_s->mac_addr_sched_scan);
    2422         612 :                 wpa_s->mac_addr_sched_scan = NULL;
    2423             :         }
    2424             : 
    2425         616 :         if (type & MAC_ADDR_RAND_PNO) {
    2426         612 :                 os_free(wpa_s->mac_addr_pno);
    2427         612 :                 wpa_s->mac_addr_pno = NULL;
    2428             :         }
    2429         616 : }
    2430             : 
    2431             : 
    2432           3 : int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
    2433             :                                 unsigned int type, const u8 *addr,
    2434             :                                 const u8 *mask)
    2435             : {
    2436           3 :         u8 *tmp = NULL;
    2437             : 
    2438           3 :         wpas_mac_addr_rand_scan_clear(wpa_s, type);
    2439             : 
    2440           3 :         if (addr) {
    2441           2 :                 tmp = os_malloc(2 * ETH_ALEN);
    2442           2 :                 if (!tmp)
    2443           0 :                         return -1;
    2444           2 :                 os_memcpy(tmp, addr, ETH_ALEN);
    2445           2 :                 os_memcpy(tmp + ETH_ALEN, mask, ETH_ALEN);
    2446             :         }
    2447             : 
    2448           3 :         if (type == MAC_ADDR_RAND_SCAN) {
    2449           3 :                 wpa_s->mac_addr_scan = tmp;
    2450           0 :         } else if (type == MAC_ADDR_RAND_SCHED_SCAN) {
    2451           0 :                 wpa_s->mac_addr_sched_scan = tmp;
    2452           0 :         } else if (type == MAC_ADDR_RAND_PNO) {
    2453           0 :                 wpa_s->mac_addr_pno = tmp;
    2454             :         } else {
    2455           0 :                 wpa_printf(MSG_INFO,
    2456             :                            "scan: Invalid MAC randomization type=0x%x",
    2457             :                            type);
    2458           0 :                 os_free(tmp);
    2459           0 :                 return -1;
    2460             :         }
    2461             : 
    2462           3 :         wpa_s->mac_addr_rand_enable |= type;
    2463           3 :         return 0;
    2464             : }

Generated by: LCOV version 1.10