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 1422976643 Lines: 745 1096 68.0 %
Date: 2015-02-03 Functions: 42 48 87.5 %

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

Generated by: LCOV version 1.10