LCOV - code coverage report
Current view: top level - src/drivers - driver_nl80211_scan.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 257 438 58.7 %
Date: 2016-10-02 Functions: 10 16 62.5 %

          Line data    Source code
       1             : /*
       2             :  * Driver interaction with Linux nl80211/cfg80211 - Scanning
       3             :  * Copyright(c) 2015 Intel Deutschland GmbH
       4             :  * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
       5             :  * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
       6             :  * Copyright (c) 2009-2010, Atheros Communications
       7             :  *
       8             :  * This software may be distributed under the terms of the BSD license.
       9             :  * See README for more details.
      10             :  */
      11             : 
      12             : #include "includes.h"
      13             : #include <netlink/genl/genl.h>
      14             : 
      15             : #include "utils/common.h"
      16             : #include "utils/eloop.h"
      17             : #include "common/ieee802_11_defs.h"
      18             : #include "common/ieee802_11_common.h"
      19             : #include "common/qca-vendor.h"
      20             : #include "driver_nl80211.h"
      21             : 
      22             : 
      23        5685 : static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)
      24             : {
      25             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
      26        5685 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
      27             :         struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
      28             :         static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
      29             :                 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
      30             :                 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
      31             :         };
      32        5685 :         struct wpa_scan_results *scan_results = arg;
      33             :         struct wpa_scan_res *scan_res;
      34             :         size_t i;
      35             : 
      36        5685 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
      37             :                   genlmsg_attrlen(gnlh, 0), NULL);
      38             : 
      39        5685 :         if (!tb[NL80211_ATTR_SURVEY_INFO]) {
      40           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Survey data missing");
      41           0 :                 return NL_SKIP;
      42             :         }
      43             : 
      44        5685 :         if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
      45             :                              tb[NL80211_ATTR_SURVEY_INFO],
      46             :                              survey_policy)) {
      47           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested "
      48             :                            "attributes");
      49           0 :                 return NL_SKIP;
      50             :         }
      51             : 
      52        5685 :         if (!sinfo[NL80211_SURVEY_INFO_NOISE])
      53           0 :                 return NL_SKIP;
      54             : 
      55        5685 :         if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
      56           0 :                 return NL_SKIP;
      57             : 
      58       12569 :         for (i = 0; i < scan_results->num; ++i) {
      59        6884 :                 scan_res = scan_results->res[i];
      60        6884 :                 if (!scan_res)
      61           0 :                         continue;
      62       13768 :                 if ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
      63        6884 :                     scan_res->freq)
      64        1587 :                         continue;
      65        5297 :                 if (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))
      66           0 :                         continue;
      67        5297 :                 scan_res->noise = (s8)
      68        5297 :                         nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
      69        5297 :                 scan_res->flags &= ~WPA_SCAN_NOISE_INVALID;
      70             :         }
      71             : 
      72        5685 :         return NL_SKIP;
      73             : }
      74             : 
      75             : 
      76        5773 : static int nl80211_get_noise_for_scan_results(
      77             :         struct wpa_driver_nl80211_data *drv,
      78             :         struct wpa_scan_results *scan_res)
      79             : {
      80             :         struct nl_msg *msg;
      81             : 
      82        5773 :         msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
      83        5773 :         return send_and_recv_msgs(drv, msg, get_noise_for_scan_results,
      84             :                                   scan_res);
      85             : }
      86             : 
      87             : 
      88             : /**
      89             :  * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion
      90             :  * @eloop_ctx: Driver private data
      91             :  * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init()
      92             :  *
      93             :  * This function can be used as registered timeout when starting a scan to
      94             :  * generate a scan completed event if the driver does not report this.
      95             :  */
      96           0 : void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
      97             : {
      98           0 :         struct wpa_driver_nl80211_data *drv = eloop_ctx;
      99             : 
     100           0 :         wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
     101           0 :         if (!wpa_driver_nl80211_abort_scan(drv->first_bss))
     102           0 :                 return;
     103             : 
     104           0 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
     105             : 
     106           0 :         if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
     107           0 :                 wpa_driver_nl80211_set_mode(drv->first_bss,
     108             :                                             drv->ap_scan_as_station);
     109           0 :                 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
     110             :         }
     111             : 
     112           0 :         wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
     113           0 :         wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
     114             : }
     115             : 
     116             : 
     117             : static struct nl_msg *
     118        5712 : nl80211_scan_common(struct i802_bss *bss, u8 cmd,
     119             :                     struct wpa_driver_scan_params *params)
     120             : {
     121        5712 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     122             :         struct nl_msg *msg;
     123             :         size_t i;
     124        5712 :         u32 scan_flags = 0;
     125             : 
     126        5712 :         msg = nl80211_cmd_msg(bss, 0, cmd);
     127        5712 :         if (!msg)
     128           0 :                 return NULL;
     129             : 
     130        5712 :         if (params->num_ssids) {
     131             :                 struct nlattr *ssids;
     132             : 
     133        5550 :                 ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
     134        5550 :                 if (ssids == NULL)
     135           0 :                         goto fail;
     136       11117 :                 for (i = 0; i < params->num_ssids; i++) {
     137       11134 :                         wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
     138        5567 :                                           params->ssids[i].ssid,
     139             :                                           params->ssids[i].ssid_len);
     140        5567 :                         if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
     141        5567 :                                     params->ssids[i].ssid))
     142           0 :                                 goto fail;
     143             :                 }
     144        5550 :                 nla_nest_end(msg, ssids);
     145             :         } else {
     146         162 :                 wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested");
     147             :         }
     148             : 
     149        5712 :         if (params->extra_ies) {
     150       11136 :                 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
     151        5568 :                             params->extra_ies, params->extra_ies_len);
     152        5568 :                 if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
     153        5568 :                             params->extra_ies))
     154           0 :                         goto fail;
     155             :         }
     156             : 
     157        5712 :         if (params->freqs) {
     158             :                 struct nlattr *freqs;
     159        5466 :                 freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
     160        5466 :                 if (freqs == NULL)
     161           0 :                         goto fail;
     162       13735 :                 for (i = 0; params->freqs[i]; i++) {
     163        8269 :                         wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
     164        8269 :                                    "MHz", params->freqs[i]);
     165        8269 :                         if (nla_put_u32(msg, i + 1, params->freqs[i]))
     166           0 :                                 goto fail;
     167             :                 }
     168        5466 :                 nla_nest_end(msg, freqs);
     169             :         }
     170             : 
     171        5712 :         os_free(drv->filter_ssids);
     172        5712 :         drv->filter_ssids = params->filter_ssids;
     173        5712 :         params->filter_ssids = NULL;
     174        5712 :         drv->num_filter_ssids = params->num_filter_ssids;
     175             : 
     176        5712 :         if (params->only_new_results) {
     177        2727 :                 wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
     178        2727 :                 scan_flags |= NL80211_SCAN_FLAG_FLUSH;
     179             :         }
     180             : 
     181        5712 :         if (params->low_priority && drv->have_low_prio_scan) {
     182           5 :                 wpa_printf(MSG_DEBUG,
     183             :                            "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
     184           5 :                 scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
     185             :         }
     186             : 
     187        5712 :         if (params->mac_addr_rand) {
     188           3 :                 wpa_printf(MSG_DEBUG,
     189             :                            "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR");
     190           3 :                 scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
     191             : 
     192           3 :                 if (params->mac_addr) {
     193          12 :                         wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR,
     194          12 :                                    MAC2STR(params->mac_addr));
     195           2 :                         if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
     196           2 :                                     params->mac_addr))
     197           0 :                                 goto fail;
     198             :                 }
     199             : 
     200           3 :                 if (params->mac_addr_mask) {
     201          12 :                         wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: "
     202          12 :                                    MACSTR, MAC2STR(params->mac_addr_mask));
     203           2 :                         if (nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
     204           2 :                                     params->mac_addr_mask))
     205           0 :                                 goto fail;
     206             :                 }
     207             :         }
     208             : 
     209        8446 :         if (scan_flags &&
     210        2734 :             nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags))
     211           0 :                 goto fail;
     212             : 
     213        5712 :         return msg;
     214             : 
     215             : fail:
     216           0 :         nlmsg_free(msg);
     217           0 :         return NULL;
     218             : }
     219             : 
     220             : 
     221             : /**
     222             :  * wpa_driver_nl80211_scan - Request the driver to initiate scan
     223             :  * @bss: Pointer to private driver data from wpa_driver_nl80211_init()
     224             :  * @params: Scan parameters
     225             :  * Returns: 0 on success, -1 on failure
     226             :  */
     227        5715 : int wpa_driver_nl80211_scan(struct i802_bss *bss,
     228             :                             struct wpa_driver_scan_params *params)
     229             : {
     230        5715 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     231        5715 :         int ret = -1, timeout;
     232        5715 :         struct nl_msg *msg = NULL;
     233             : 
     234        5715 :         wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
     235        5715 :         drv->scan_for_auth = 0;
     236             : 
     237        5715 :         if (TEST_FAIL())
     238           3 :                 return -1;
     239             : 
     240        5712 :         msg = nl80211_scan_common(bss, NL80211_CMD_TRIGGER_SCAN, params);
     241        5712 :         if (!msg)
     242           0 :                 return -1;
     243             : 
     244        5712 :         if (params->p2p_probe) {
     245             :                 struct nlattr *rates;
     246             : 
     247        1436 :                 wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
     248             : 
     249        1436 :                 rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
     250        1436 :                 if (rates == NULL)
     251           0 :                         goto fail;
     252             : 
     253             :                 /*
     254             :                  * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
     255             :                  * by masking out everything else apart from the OFDM rates 6,
     256             :                  * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
     257             :                  * rates are left enabled.
     258             :                  */
     259        1436 :                 if (nla_put(msg, NL80211_BAND_2GHZ, 8,
     260             :                             "\x0c\x12\x18\x24\x30\x48\x60\x6c"))
     261           0 :                         goto fail;
     262        1436 :                 nla_nest_end(msg, rates);
     263             : 
     264        1436 :                 if (nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE))
     265           0 :                         goto fail;
     266             :         }
     267             : 
     268        5712 :         if (params->bssid) {
     269          48 :                 wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: "
     270          48 :                            MACSTR, MAC2STR(params->bssid));
     271           8 :                 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
     272           0 :                         goto fail;
     273             :         }
     274             : 
     275        5712 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
     276        5712 :         msg = NULL;
     277        5712 :         if (ret) {
     278           5 :                 wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
     279             :                            "(%s)", ret, strerror(-ret));
     280           5 :                 if (drv->hostapd && is_ap_interface(drv->nlmode)) {
     281           0 :                         enum nl80211_iftype old_mode = drv->nlmode;
     282             : 
     283             :                         /*
     284             :                          * mac80211 does not allow scan requests in AP mode, so
     285             :                          * try to do this in station mode.
     286             :                          */
     287           0 :                         if (wpa_driver_nl80211_set_mode(
     288             :                                     bss, NL80211_IFTYPE_STATION))
     289           0 :                                 goto fail;
     290             : 
     291           0 :                         if (wpa_driver_nl80211_scan(bss, params)) {
     292           0 :                                 wpa_driver_nl80211_set_mode(bss, old_mode);
     293           0 :                                 goto fail;
     294             :                         }
     295             : 
     296             :                         /* Restore AP mode when processing scan results */
     297           0 :                         drv->ap_scan_as_station = old_mode;
     298           0 :                         ret = 0;
     299             :                 } else
     300             :                         goto fail;
     301             :         }
     302             : 
     303        5707 :         drv->scan_state = SCAN_REQUESTED;
     304             :         /* Not all drivers generate "scan completed" wireless event, so try to
     305             :          * read results after a timeout. */
     306        5707 :         timeout = 10;
     307        5707 :         if (drv->scan_complete_events) {
     308             :                 /*
     309             :                  * The driver seems to deliver events to notify when scan is
     310             :                  * complete, so use longer timeout to avoid race conditions
     311             :                  * with scanning and following association request.
     312             :                  */
     313        5191 :                 timeout = 30;
     314             :         }
     315        5707 :         wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
     316             :                    "seconds", ret, timeout);
     317        5707 :         eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
     318        5707 :         eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
     319             :                                drv, drv->ctx);
     320        5707 :         drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
     321             : 
     322             : fail:
     323        5712 :         nlmsg_free(msg);
     324        5712 :         return ret;
     325             : }
     326             : 
     327             : 
     328             : static int
     329           0 : nl80211_sched_scan_add_scan_plans(struct wpa_driver_nl80211_data *drv,
     330             :                                   struct nl_msg *msg,
     331             :                                   struct wpa_driver_scan_params *params)
     332             : {
     333             :         struct nlattr *plans;
     334           0 :         struct sched_scan_plan *scan_plans = params->sched_scan_plans;
     335             :         unsigned int i;
     336             : 
     337           0 :         plans = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
     338           0 :         if (!plans)
     339           0 :                 return -1;
     340             : 
     341           0 :         for (i = 0; i < params->sched_scan_plans_num; i++) {
     342           0 :                 struct nlattr *plan = nla_nest_start(msg, i + 1);
     343             : 
     344           0 :                 if (!plan)
     345           0 :                         return -1;
     346             : 
     347           0 :                 if (!scan_plans[i].interval ||
     348           0 :                     scan_plans[i].interval >
     349           0 :                     drv->capa.max_sched_scan_plan_interval) {
     350           0 :                         wpa_printf(MSG_DEBUG,
     351             :                                    "nl80211: sched scan plan no. %u: Invalid interval: %u",
     352           0 :                                    i, scan_plans[i].interval);
     353           0 :                         return -1;
     354             :                 }
     355             : 
     356           0 :                 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
     357           0 :                                 scan_plans[i].interval))
     358           0 :                         return -1;
     359             : 
     360           0 :                 if (scan_plans[i].iterations >
     361           0 :                     drv->capa.max_sched_scan_plan_iterations) {
     362           0 :                         wpa_printf(MSG_DEBUG,
     363             :                                    "nl80211: sched scan plan no. %u: Invalid number of iterations: %u",
     364           0 :                                    i, scan_plans[i].iterations);
     365           0 :                         return -1;
     366             :                 }
     367             : 
     368           0 :                 if (scan_plans[i].iterations &&
     369           0 :                     nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
     370           0 :                                 scan_plans[i].iterations))
     371           0 :                         return -1;
     372             : 
     373           0 :                 nla_nest_end(msg, plan);
     374             : 
     375             :                 /*
     376             :                  * All the scan plans must specify the number of iterations
     377             :                  * except the last plan, which will run infinitely. So if the
     378             :                  * number of iterations is not specified, this ought to be the
     379             :                  * last scan plan.
     380             :                  */
     381           0 :                 if (!scan_plans[i].iterations)
     382           0 :                         break;
     383             :         }
     384             : 
     385           0 :         if (i != params->sched_scan_plans_num - 1) {
     386           0 :                 wpa_printf(MSG_DEBUG,
     387             :                            "nl80211: All sched scan plans but the last must specify number of iterations");
     388           0 :                 return -1;
     389             :         }
     390             : 
     391           0 :         nla_nest_end(msg, plans);
     392           0 :         return 0;
     393             : }
     394             : 
     395             : 
     396             : /**
     397             :  * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
     398             :  * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
     399             :  * @params: Scan parameters
     400             :  * Returns: 0 on success, -1 on failure or if not supported
     401             :  */
     402           0 : int wpa_driver_nl80211_sched_scan(void *priv,
     403             :                                   struct wpa_driver_scan_params *params)
     404             : {
     405           0 :         struct i802_bss *bss = priv;
     406           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     407           0 :         int ret = -1;
     408             :         struct nl_msg *msg;
     409             :         size_t i;
     410             : 
     411           0 :         wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
     412             : 
     413             : #ifdef ANDROID
     414             :         if (!drv->capa.sched_scan_supported)
     415             :                 return android_pno_start(bss, params);
     416             : #endif /* ANDROID */
     417             : 
     418           0 :         if (!params->sched_scan_plans_num ||
     419           0 :             params->sched_scan_plans_num > drv->capa.max_sched_scan_plans) {
     420           0 :                 wpa_printf(MSG_ERROR,
     421             :                            "nl80211: Invalid number of sched scan plans: %u",
     422             :                            params->sched_scan_plans_num);
     423           0 :                 return -1;
     424             :         }
     425             : 
     426           0 :         msg = nl80211_scan_common(bss, NL80211_CMD_START_SCHED_SCAN, params);
     427           0 :         if (!msg)
     428           0 :                 goto fail;
     429             : 
     430           0 :         if (drv->capa.max_sched_scan_plan_iterations) {
     431           0 :                 if (nl80211_sched_scan_add_scan_plans(drv, msg, params))
     432           0 :                         goto fail;
     433             :         } else {
     434           0 :                 if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
     435           0 :                                 params->sched_scan_plans[0].interval * 1000))
     436           0 :                         goto fail;
     437             :         }
     438             : 
     439           0 :         if ((drv->num_filter_ssids &&
     440           0 :             (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
     441           0 :             params->filter_rssi) {
     442             :                 struct nlattr *match_sets;
     443           0 :                 match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
     444           0 :                 if (match_sets == NULL)
     445           0 :                         goto fail;
     446             : 
     447           0 :                 for (i = 0; i < drv->num_filter_ssids; i++) {
     448             :                         struct nlattr *match_set_ssid;
     449           0 :                         wpa_hexdump_ascii(MSG_MSGDUMP,
     450             :                                           "nl80211: Sched scan filter SSID",
     451           0 :                                           drv->filter_ssids[i].ssid,
     452           0 :                                           drv->filter_ssids[i].ssid_len);
     453             : 
     454           0 :                         match_set_ssid = nla_nest_start(msg, i + 1);
     455           0 :                         if (match_set_ssid == NULL ||
     456           0 :                             nla_put(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
     457           0 :                                     drv->filter_ssids[i].ssid_len,
     458           0 :                                     drv->filter_ssids[i].ssid) ||
     459           0 :                             (params->filter_rssi &&
     460           0 :                              nla_put_u32(msg,
     461             :                                          NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
     462           0 :                                          params->filter_rssi)))
     463             :                                 goto fail;
     464             : 
     465           0 :                         nla_nest_end(msg, match_set_ssid);
     466             :                 }
     467             : 
     468             :                 /*
     469             :                  * Due to backward compatibility code, newer kernels treat this
     470             :                  * matchset (with only an RSSI filter) as the default for all
     471             :                  * other matchsets, unless it's the only one, in which case the
     472             :                  * matchset will actually allow all SSIDs above the RSSI.
     473             :                  */
     474           0 :                 if (params->filter_rssi) {
     475             :                         struct nlattr *match_set_rssi;
     476           0 :                         match_set_rssi = nla_nest_start(msg, 0);
     477           0 :                         if (match_set_rssi == NULL ||
     478           0 :                             nla_put_u32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
     479           0 :                                         params->filter_rssi))
     480             :                                 goto fail;
     481           0 :                         wpa_printf(MSG_MSGDUMP,
     482             :                                    "nl80211: Sched scan RSSI filter %d dBm",
     483             :                                    params->filter_rssi);
     484           0 :                         nla_nest_end(msg, match_set_rssi);
     485             :                 }
     486             : 
     487           0 :                 nla_nest_end(msg, match_sets);
     488             :         }
     489             : 
     490           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
     491             : 
     492             :         /* TODO: if we get an error here, we should fall back to normal scan */
     493             : 
     494           0 :         msg = NULL;
     495           0 :         if (ret) {
     496           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: "
     497             :                            "ret=%d (%s)", ret, strerror(-ret));
     498           0 :                 goto fail;
     499             :         }
     500             : 
     501           0 :         wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d)", ret);
     502             : 
     503             : fail:
     504           0 :         nlmsg_free(msg);
     505           0 :         return ret;
     506             : }
     507             : 
     508             : 
     509             : /**
     510             :  * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan
     511             :  * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
     512             :  * Returns: 0 on success, -1 on failure or if not supported
     513             :  */
     514           0 : int wpa_driver_nl80211_stop_sched_scan(void *priv)
     515             : {
     516           0 :         struct i802_bss *bss = priv;
     517           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     518             :         int ret;
     519             :         struct nl_msg *msg;
     520             : 
     521             : #ifdef ANDROID
     522             :         if (!drv->capa.sched_scan_supported)
     523             :                 return android_pno_stop(bss);
     524             : #endif /* ANDROID */
     525             : 
     526           0 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN);
     527           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
     528           0 :         if (ret) {
     529           0 :                 wpa_printf(MSG_DEBUG,
     530             :                            "nl80211: Sched scan stop failed: ret=%d (%s)",
     531             :                            ret, strerror(-ret));
     532             :         } else {
     533           0 :                 wpa_printf(MSG_DEBUG,
     534             :                            "nl80211: Sched scan stop sent");
     535             :         }
     536             : 
     537           0 :         return ret;
     538             : }
     539             : 
     540             : 
     541        7020 : static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
     542             :                                  const u8 *ie, size_t ie_len)
     543             : {
     544             :         const u8 *ssid;
     545             :         size_t i;
     546             : 
     547        7020 :         if (drv->filter_ssids == NULL)
     548        7016 :                 return 0;
     549             : 
     550           4 :         ssid = get_ie(ie, ie_len, WLAN_EID_SSID);
     551           4 :         if (ssid == NULL)
     552           0 :                 return 1;
     553             : 
     554           7 :         for (i = 0; i < drv->num_filter_ssids; i++) {
     555           5 :                 if (ssid[1] == drv->filter_ssids[i].ssid_len &&
     556           1 :                     os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==
     557             :                     0)
     558           1 :                         return 0;
     559             :         }
     560             : 
     561           3 :         return 1;
     562             : }
     563             : 
     564             : 
     565        7470 : int bss_info_handler(struct nl_msg *msg, void *arg)
     566             : {
     567             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
     568        7470 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     569             :         struct nlattr *bss[NL80211_BSS_MAX + 1];
     570             :         static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
     571             :                 [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
     572             :                 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
     573             :                 [NL80211_BSS_TSF] = { .type = NLA_U64 },
     574             :                 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
     575             :                 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
     576             :                 [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
     577             :                 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
     578             :                 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
     579             :                 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
     580             :                 [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
     581             :                 [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
     582             :         };
     583        7470 :         struct nl80211_bss_info_arg *_arg = arg;
     584        7470 :         struct wpa_scan_results *res = _arg->res;
     585             :         struct wpa_scan_res **tmp;
     586             :         struct wpa_scan_res *r;
     587             :         const u8 *ie, *beacon_ie;
     588             :         size_t ie_len, beacon_ie_len;
     589             :         u8 *pos;
     590             :         size_t i;
     591             : 
     592        7470 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     593             :                   genlmsg_attrlen(gnlh, 0), NULL);
     594        7470 :         if (!tb[NL80211_ATTR_BSS])
     595           0 :                 return NL_SKIP;
     596        7470 :         if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
     597             :                              bss_policy))
     598           0 :                 return NL_SKIP;
     599        7470 :         if (bss[NL80211_BSS_STATUS]) {
     600             :                 enum nl80211_bss_status status;
     601         573 :                 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
     602        1071 :                 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
     603         498 :                     bss[NL80211_BSS_FREQUENCY]) {
     604         498 :                         _arg->assoc_freq =
     605         498 :                                 nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
     606         498 :                         wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
     607             :                                    _arg->assoc_freq);
     608             :                 }
     609         648 :                 if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
     610          75 :                     bss[NL80211_BSS_FREQUENCY]) {
     611          75 :                         _arg->ibss_freq =
     612          75 :                                 nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
     613          75 :                         wpa_printf(MSG_DEBUG, "nl80211: IBSS-joined on %u MHz",
     614             :                                    _arg->ibss_freq);
     615             :                 }
     616        1071 :                 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
     617         498 :                     bss[NL80211_BSS_BSSID]) {
     618         498 :                         os_memcpy(_arg->assoc_bssid,
     619             :                                   nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
     620        2988 :                         wpa_printf(MSG_DEBUG, "nl80211: Associated with "
     621        2988 :                                    MACSTR, MAC2STR(_arg->assoc_bssid));
     622             :                 }
     623             :         }
     624        7470 :         if (!res)
     625         450 :                 return NL_SKIP;
     626        7020 :         if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
     627        7020 :                 ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
     628        7020 :                 ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
     629             :         } else {
     630           0 :                 ie = NULL;
     631           0 :                 ie_len = 0;
     632             :         }
     633        7020 :         if (bss[NL80211_BSS_BEACON_IES]) {
     634        4806 :                 beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);
     635        4806 :                 beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);
     636             :         } else {
     637        2214 :                 beacon_ie = NULL;
     638        2214 :                 beacon_ie_len = 0;
     639             :         }
     640             : 
     641        7020 :         if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie,
     642             :                                   ie ? ie_len : beacon_ie_len))
     643           3 :                 return NL_SKIP;
     644             : 
     645        7017 :         r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
     646        7017 :         if (r == NULL)
     647           0 :                 return NL_SKIP;
     648        7017 :         if (bss[NL80211_BSS_BSSID])
     649        7017 :                 os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),
     650             :                           ETH_ALEN);
     651        7017 :         if (bss[NL80211_BSS_FREQUENCY])
     652        7017 :                 r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
     653        7017 :         if (bss[NL80211_BSS_BEACON_INTERVAL])
     654        7017 :                 r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
     655        7017 :         if (bss[NL80211_BSS_CAPABILITY])
     656        7017 :                 r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
     657        7017 :         r->flags |= WPA_SCAN_NOISE_INVALID;
     658        7017 :         if (bss[NL80211_BSS_SIGNAL_MBM]) {
     659        7017 :                 r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
     660        7017 :                 r->level /= 100; /* mBm to dBm */
     661        7017 :                 r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;
     662           0 :         } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
     663           0 :                 r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
     664           0 :                 r->flags |= WPA_SCAN_QUAL_INVALID;
     665             :         } else
     666           0 :                 r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;
     667        7017 :         if (bss[NL80211_BSS_TSF])
     668        7017 :                 r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);
     669        7017 :         if (bss[NL80211_BSS_BEACON_TSF]) {
     670        4803 :                 u64 tsf = nla_get_u64(bss[NL80211_BSS_BEACON_TSF]);
     671        4803 :                 if (tsf > r->tsf)
     672        2329 :                         r->tsf = tsf;
     673             :         }
     674        7017 :         if (bss[NL80211_BSS_SEEN_MS_AGO])
     675        7017 :                 r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
     676        7017 :         r->ie_len = ie_len;
     677        7017 :         pos = (u8 *) (r + 1);
     678        7017 :         if (ie) {
     679        7017 :                 os_memcpy(pos, ie, ie_len);
     680        7017 :                 pos += ie_len;
     681             :         }
     682        7017 :         r->beacon_ie_len = beacon_ie_len;
     683        7017 :         if (beacon_ie)
     684        4803 :                 os_memcpy(pos, beacon_ie, beacon_ie_len);
     685             : 
     686        7017 :         if (bss[NL80211_BSS_STATUS]) {
     687             :                 enum nl80211_bss_status status;
     688         246 :                 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
     689         246 :                 switch (status) {
     690             :                 case NL80211_BSS_STATUS_ASSOCIATED:
     691         228 :                         r->flags |= WPA_SCAN_ASSOCIATED;
     692         228 :                         break;
     693             :                 default:
     694          18 :                         break;
     695             :                 }
     696             :         }
     697             : 
     698             :         /*
     699             :          * cfg80211 maintains separate BSS table entries for APs if the same
     700             :          * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
     701             :          * not use frequency as a separate key in the BSS table, so filter out
     702             :          * duplicated entries. Prefer associated BSS entry in such a case in
     703             :          * order to get the correct frequency into the BSS table. Similarly,
     704             :          * prefer newer entries over older.
     705             :          */
     706        9341 :         for (i = 0; i < res->num; i++) {
     707             :                 const u8 *s1, *s2;
     708        2350 :                 if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
     709        1903 :                         continue;
     710             : 
     711         447 :                 s1 = get_ie((u8 *) (res->res[i] + 1),
     712         447 :                             res->res[i]->ie_len, WLAN_EID_SSID);
     713         447 :                 s2 = get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
     714         603 :                 if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
     715         156 :                     os_memcmp(s1, s2, 2 + s1[1]) != 0)
     716         421 :                         continue;
     717             : 
     718             :                 /* Same BSSID,SSID was already included in scan results */
     719         156 :                 wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result "
     720         156 :                            "for " MACSTR, MAC2STR(r->bssid));
     721             : 
     722          26 :                 if (((r->flags & WPA_SCAN_ASSOCIATED) &&
     723          26 :                      !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) ||
     724          26 :                     r->age < res->res[i]->age) {
     725          19 :                         os_free(res->res[i]);
     726          19 :                         res->res[i] = r;
     727             :                 } else
     728           7 :                         os_free(r);
     729          26 :                 return NL_SKIP;
     730             :         }
     731             : 
     732        6991 :         tmp = os_realloc_array(res->res, res->num + 1,
     733             :                                sizeof(struct wpa_scan_res *));
     734        6991 :         if (tmp == NULL) {
     735           0 :                 os_free(r);
     736           0 :                 return NL_SKIP;
     737             :         }
     738        6991 :         tmp[res->num++] = r;
     739        6991 :         res->res = tmp;
     740             : 
     741        6991 :         return NL_SKIP;
     742             : }
     743             : 
     744             : 
     745           0 : static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
     746             :                                  const u8 *addr)
     747             : {
     748           0 :         if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
     749           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Clear possible state "
     750           0 :                            "mismatch (" MACSTR ")", MAC2STR(addr));
     751           0 :                 wpa_driver_nl80211_mlme(drv, addr,
     752             :                                         NL80211_CMD_DEAUTHENTICATE,
     753             :                                         WLAN_REASON_PREV_AUTH_NOT_VALID, 1);
     754             :         }
     755           0 : }
     756             : 
     757             : 
     758        5773 : static void wpa_driver_nl80211_check_bss_status(
     759             :         struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res)
     760             : {
     761             :         size_t i;
     762             : 
     763       12764 :         for (i = 0; i < res->num; i++) {
     764        6991 :                 struct wpa_scan_res *r = res->res[i];
     765             : 
     766        6991 :                 if (r->flags & WPA_SCAN_ASSOCIATED) {
     767        1368 :                         wpa_printf(MSG_DEBUG, "nl80211: Scan results "
     768             :                                    "indicate BSS status with " MACSTR
     769             :                                    " as associated",
     770        1368 :                                    MAC2STR(r->bssid));
     771         456 :                         if (is_sta_interface(drv->nlmode) &&
     772         228 :                             !drv->associated) {
     773           0 :                                 wpa_printf(MSG_DEBUG, "nl80211: Local state "
     774             :                                            "(not associated) does not match "
     775             :                                            "with BSS state");
     776           0 :                                 clear_state_mismatch(drv, r->bssid);
     777         456 :                         } else if (is_sta_interface(drv->nlmode) &&
     778         228 :                                    os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
     779             :                                    0) {
     780           0 :                                 wpa_printf(MSG_DEBUG, "nl80211: Local state "
     781             :                                            "(associated with " MACSTR ") does "
     782             :                                            "not match with BSS state",
     783           0 :                                            MAC2STR(drv->bssid));
     784           0 :                                 clear_state_mismatch(drv, r->bssid);
     785           0 :                                 clear_state_mismatch(drv, drv->bssid);
     786             :                         }
     787             :                 }
     788             :         }
     789        5773 : }
     790             : 
     791             : 
     792             : static struct wpa_scan_results *
     793        5774 : nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
     794             : {
     795             :         struct nl_msg *msg;
     796             :         struct wpa_scan_results *res;
     797             :         int ret;
     798             :         struct nl80211_bss_info_arg arg;
     799             : 
     800        5774 :         res = os_zalloc(sizeof(*res));
     801        5774 :         if (res == NULL)
     802           1 :                 return NULL;
     803        5773 :         if (!(msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP,
     804             :                                     NL80211_CMD_GET_SCAN))) {
     805           0 :                 wpa_scan_results_free(res);
     806           0 :                 return NULL;
     807             :         }
     808             : 
     809        5773 :         arg.drv = drv;
     810        5773 :         arg.res = res;
     811        5773 :         ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
     812        5773 :         if (ret == 0) {
     813        5773 :                 wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu "
     814             :                            "BSSes)", (unsigned long) res->num);
     815        5773 :                 nl80211_get_noise_for_scan_results(drv, res);
     816        5773 :                 return res;
     817             :         }
     818           0 :         wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
     819             :                    "(%s)", ret, strerror(-ret));
     820           0 :         wpa_scan_results_free(res);
     821           0 :         return NULL;
     822             : }
     823             : 
     824             : 
     825             : /**
     826             :  * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
     827             :  * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
     828             :  * Returns: Scan results on success, -1 on failure
     829             :  */
     830        5774 : struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv)
     831             : {
     832        5774 :         struct i802_bss *bss = priv;
     833        5774 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     834             :         struct wpa_scan_results *res;
     835             : 
     836        5774 :         res = nl80211_get_scan_results(drv);
     837        5774 :         if (res)
     838        5773 :                 wpa_driver_nl80211_check_bss_status(drv, res);
     839        5774 :         return res;
     840             : }
     841             : 
     842             : 
     843           0 : void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
     844             : {
     845             :         struct wpa_scan_results *res;
     846             :         size_t i;
     847             : 
     848           0 :         res = nl80211_get_scan_results(drv);
     849           0 :         if (res == NULL) {
     850           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results");
     851           0 :                 return;
     852             :         }
     853             : 
     854           0 :         wpa_printf(MSG_DEBUG, "nl80211: Scan result dump");
     855           0 :         for (i = 0; i < res->num; i++) {
     856           0 :                 struct wpa_scan_res *r = res->res[i];
     857           0 :                 wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s",
     858           0 :                            (int) i, (int) res->num, MAC2STR(r->bssid),
     859           0 :                            r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : "");
     860             :         }
     861             : 
     862           0 :         wpa_scan_results_free(res);
     863             : }
     864             : 
     865             : 
     866          60 : int wpa_driver_nl80211_abort_scan(void *priv)
     867             : {
     868          60 :         struct i802_bss *bss = priv;
     869          60 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     870             :         int ret;
     871             :         struct nl_msg *msg;
     872             : 
     873          60 :         wpa_printf(MSG_DEBUG, "nl80211: Abort scan");
     874          60 :         msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN);
     875          60 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
     876          60 :         if (ret) {
     877           4 :                 wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)",
     878             :                            ret, strerror(-ret));
     879             :         }
     880             : 
     881          60 :         return ret;
     882             : }
     883             : 
     884             : 
     885             : #ifdef CONFIG_DRIVER_NL80211_QCA
     886             : 
     887             : static int scan_cookie_handler(struct nl_msg *msg, void *arg)
     888             : {
     889             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
     890             :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     891             :         u64 *cookie = arg;
     892             : 
     893             :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     894             :                   genlmsg_attrlen(gnlh, 0), NULL);
     895             : 
     896             :         if (tb[NL80211_ATTR_VENDOR_DATA]) {
     897             :                 struct nlattr *nl_vendor = tb[NL80211_ATTR_VENDOR_DATA];
     898             :                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
     899             : 
     900             :                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
     901             :                           nla_data(nl_vendor), nla_len(nl_vendor), NULL);
     902             : 
     903             :                 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE])
     904             :                         *cookie = nla_get_u64(
     905             :                                 tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
     906             :         }
     907             : 
     908             :         return NL_SKIP;
     909             : }
     910             : 
     911             : 
     912             : /**
     913             :  * wpa_driver_nl80211_vendor_scan - Request the driver to initiate a vendor scan
     914             :  * @bss: Pointer to private driver data from wpa_driver_nl80211_init()
     915             :  * @params: Scan parameters
     916             :  * Returns: 0 on success, -1 on failure
     917             :  */
     918             : int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
     919             :                                    struct wpa_driver_scan_params *params)
     920             : {
     921             :         struct wpa_driver_nl80211_data *drv = bss->drv;
     922             :         struct nl_msg *msg = NULL;
     923             :         struct nlattr *attr;
     924             :         size_t i;
     925             :         u32 scan_flags = 0;
     926             :         int ret = -1;
     927             :         u64 cookie = 0;
     928             : 
     929             :         wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: vendor scan request");
     930             :         drv->scan_for_auth = 0;
     931             : 
     932             :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
     933             :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
     934             :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
     935             :                         QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) )
     936             :                 goto fail;
     937             : 
     938             :         attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
     939             :         if (attr == NULL)
     940             :                 goto fail;
     941             : 
     942             :         if (params->num_ssids) {
     943             :                 struct nlattr *ssids;
     944             : 
     945             :                 ssids = nla_nest_start(msg, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS);
     946             :                 if (ssids == NULL)
     947             :                         goto fail;
     948             :                 for (i = 0; i < params->num_ssids; i++) {
     949             :                         wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
     950             :                                         params->ssids[i].ssid,
     951             :                                         params->ssids[i].ssid_len);
     952             :                         if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
     953             :                                     params->ssids[i].ssid))
     954             :                                 goto fail;
     955             :                 }
     956             :                 nla_nest_end(msg, ssids);
     957             :         }
     958             : 
     959             :         if (params->extra_ies) {
     960             :                 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
     961             :                             params->extra_ies, params->extra_ies_len);
     962             :                 if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_IE,
     963             :                             params->extra_ies_len, params->extra_ies))
     964             :                         goto fail;
     965             :         }
     966             : 
     967             :         if (params->freqs) {
     968             :                 struct nlattr *freqs;
     969             : 
     970             :                 freqs = nla_nest_start(msg,
     971             :                                        QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES);
     972             :                 if (freqs == NULL)
     973             :                         goto fail;
     974             :                 for (i = 0; params->freqs[i]; i++) {
     975             :                         wpa_printf(MSG_MSGDUMP,
     976             :                                    "nl80211: Scan frequency %u MHz",
     977             :                                    params->freqs[i]);
     978             :                         if (nla_put_u32(msg, i + 1, params->freqs[i]))
     979             :                                 goto fail;
     980             :                 }
     981             :                 nla_nest_end(msg, freqs);
     982             :         }
     983             : 
     984             :         os_free(drv->filter_ssids);
     985             :         drv->filter_ssids = params->filter_ssids;
     986             :         params->filter_ssids = NULL;
     987             :         drv->num_filter_ssids = params->num_filter_ssids;
     988             : 
     989             :         if (params->low_priority && drv->have_low_prio_scan) {
     990             :                 wpa_printf(MSG_DEBUG,
     991             :                            "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
     992             :                 scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
     993             :         }
     994             : 
     995             :         if (params->mac_addr_rand) {
     996             :                 wpa_printf(MSG_DEBUG,
     997             :                            "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR");
     998             :                 scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
     999             : 
    1000             :                 if (params->mac_addr) {
    1001             :                         wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR,
    1002             :                                    MAC2STR(params->mac_addr));
    1003             :                         if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC,
    1004             :                                     ETH_ALEN, params->mac_addr))
    1005             :                                 goto fail;
    1006             :                 }
    1007             : 
    1008             :                 if (params->mac_addr_mask) {
    1009             :                         wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: "
    1010             :                                    MACSTR, MAC2STR(params->mac_addr_mask));
    1011             :                         if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK,
    1012             :                                     ETH_ALEN, params->mac_addr_mask))
    1013             :                                 goto fail;
    1014             :                 }
    1015             :         }
    1016             : 
    1017             :         if (scan_flags &&
    1018             :             nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags))
    1019             :                 goto fail;
    1020             : 
    1021             :         if (params->p2p_probe) {
    1022             :                 struct nlattr *rates;
    1023             : 
    1024             :                 wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
    1025             : 
    1026             :                 rates = nla_nest_start(msg,
    1027             :                                        QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES);
    1028             :                 if (rates == NULL)
    1029             :                         goto fail;
    1030             : 
    1031             :                 /*
    1032             :                  * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
    1033             :                  * by masking out everything else apart from the OFDM rates 6,
    1034             :                  * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
    1035             :                  * rates are left enabled.
    1036             :                  */
    1037             :                 if (nla_put(msg, NL80211_BAND_2GHZ, 8,
    1038             :                             "\x0c\x12\x18\x24\x30\x48\x60\x6c"))
    1039             :                         goto fail;
    1040             :                 nla_nest_end(msg, rates);
    1041             : 
    1042             :                 if (nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE))
    1043             :                         goto fail;
    1044             :         }
    1045             : 
    1046             :         nla_nest_end(msg, attr);
    1047             : 
    1048             :         ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie);
    1049             :         msg = NULL;
    1050             :         if (ret) {
    1051             :                 wpa_printf(MSG_DEBUG,
    1052             :                            "nl80211: Vendor scan trigger failed: ret=%d (%s)",
    1053             :                            ret, strerror(-ret));
    1054             :                 goto fail;
    1055             :         }
    1056             : 
    1057             :         drv->vendor_scan_cookie = cookie;
    1058             :         drv->scan_state = SCAN_REQUESTED;
    1059             : 
    1060             :         wpa_printf(MSG_DEBUG,
    1061             :                    "nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
    1062             :                    ret, (long long unsigned int) cookie);
    1063             :         eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
    1064             :         eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
    1065             :                                drv, drv->ctx);
    1066             :         drv->last_scan_cmd = NL80211_CMD_VENDOR;
    1067             : 
    1068             : fail:
    1069             :         nlmsg_free(msg);
    1070             :         return ret;
    1071             : }
    1072             : 
    1073             : 
    1074             : /**
    1075             :  * nl80211_set_default_scan_ies - Set the scan default IEs to the driver
    1076             :  * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
    1077             :  * @ies: Pointer to IEs buffer
    1078             :  * @ies_len: Length of IEs in bytes
    1079             :  * Returns: 0 on success, -1 on failure
    1080             :  */
    1081             : int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len)
    1082             : {
    1083             :         struct i802_bss *bss = priv;
    1084             :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1085             :         struct nl_msg *msg = NULL;
    1086             :         struct nlattr *attr;
    1087             :         int ret = -1;
    1088             : 
    1089             :         if (!drv->set_wifi_conf_vendor_cmd_avail)
    1090             :                 return -1;
    1091             : 
    1092             :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
    1093             :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
    1094             :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
    1095             :                         QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION))
    1096             :                 goto fail;
    1097             : 
    1098             :         attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
    1099             :         if (attr == NULL)
    1100             :                 goto fail;
    1101             : 
    1102             :         wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan default IEs", ies, ies_len);
    1103             :         if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
    1104             :                     ies_len, ies))
    1105             :                 goto fail;
    1106             : 
    1107             :         nla_nest_end(msg, attr);
    1108             : 
    1109             :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    1110             :         msg = NULL;
    1111             :         if (ret) {
    1112             :                 wpa_printf(MSG_ERROR,
    1113             :                            "nl80211: Set scan default IEs failed: ret=%d (%s)",
    1114             :                            ret, strerror(-ret));
    1115             :                 goto fail;
    1116             :         }
    1117             : 
    1118             : fail:
    1119             :         nlmsg_free(msg);
    1120             :         return ret;
    1121             : }
    1122             : 
    1123             : #endif /* CONFIG_DRIVER_NL80211_QCA */

Generated by: LCOV version 1.10