16c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/* 26c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Driver interaction with Linux nl80211/cfg80211 - Scanning 3d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * Copyright(c) 2015 Intel Deutschland GmbH 46c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> 56c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net> 66c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications 76c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 86c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This software may be distributed under the terms of the BSD license. 96c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * See README for more details. 106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "includes.h" 13d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#include <time.h> 146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include <netlink/genl/genl.h> 156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "utils/common.h" 176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "utils/eloop.h" 186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "common/ieee802_11_defs.h" 1957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "common/ieee802_11_common.h" 20d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "common/qca-vendor.h" 216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "driver_nl80211.h" 226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 24abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#define MAX_NL80211_NOISE_FREQS 50 25abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 26abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstruct nl80211_noise_info { 27abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt u32 freq[MAX_NL80211_NOISE_FREQS]; 28abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt s8 noise[MAX_NL80211_NOISE_FREQS]; 29abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt unsigned int count; 30abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}; 31abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int get_noise_for_scan_results(struct nl_msg *msg, void *arg) 336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1]; 376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = { 386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, 396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, 406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 41abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_noise_info *info = arg; 42abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 43abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (info->count >= MAX_NL80211_NOISE_FREQS) 44abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_STOP; 456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_SURVEY_INFO]) { 506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Survey data missing"); 516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX, 556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tb[NL80211_ATTR_SURVEY_INFO], 566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_policy)) { 576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested " 586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "attributes"); 596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_NOISE]) 636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) 666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt info->freq[info->count] = 69abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]); 70abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt info->noise[info->count] = 71abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]); 72abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt info->count++; 736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_get_noise_for_scan_results( 79abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv, struct nl80211_noise_info *info) 806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 83abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_memset(info, 0, sizeof(*info)); 846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); 85abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info); 86abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 87abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 88abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 89abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int nl80211_abort_scan(struct i802_bss *bss) 90abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 91abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt int ret; 92abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg; 93abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 94abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 95abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Abort scan"); 96abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN); 97abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 98abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (ret) { 99abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)", 100abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ret, strerror(-ret)); 101abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 102abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return ret; 103abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 104abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 105abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 106abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 107abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int nl80211_abort_vendor_scan(struct wpa_driver_nl80211_data *drv, 108abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt u64 scan_cookie) 109abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 110abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg; 111abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nlattr *params; 112abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt int ret; 113abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 114abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Abort vendor scan with cookie 0x%llx", 115abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt (long long unsigned int) scan_cookie); 116abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 117abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR); 118abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!msg || 119abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 120abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 121abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN) || 122abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || 123abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_put_u64(msg, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, scan_cookie)) 124abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt goto fail; 125abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 126abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_nest_end(msg, params); 127abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 128abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 129abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = NULL; 130abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (ret) { 131abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_INFO, 132abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt "nl80211: Aborting vendor scan with cookie 0x%llx failed: ret=%d (%s)", 133abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt (long long unsigned int) scan_cookie, ret, 134abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt strerror(-ret)); 135abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt goto fail; 136abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 137abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return 0; 138abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtfail: 139abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nlmsg_free(msg); 140abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return -1; 1416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 142abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 1436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 1466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion 1476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @eloop_ctx: Driver private data 1486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init() 1496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 1506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This function can be used as registered timeout when starting a scan to 1516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * generate a scan completed event if the driver does not report this. 1526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 1536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) 1546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 1556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = eloop_ctx; 1569c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1579c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it"); 158abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 159abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (drv->vendor_scan_cookie && 160092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0) 161abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return; 162abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 163abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!drv->vendor_scan_cookie && 164abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nl80211_abort_scan(drv->first_bss) == 0) 1659c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt return; 1669c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1679c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan"); 1689c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) { 1706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_set_mode(drv->first_bss, 1716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ap_scan_as_station); 1726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; 1736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 1749c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1759c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results"); 1766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 1776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 1786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct nl_msg * 1816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtnl80211_scan_common(struct i802_bss *bss, u8 cmd, 1826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_scan_params *params) 1836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 1846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 1856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 1866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 1876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 scan_flags = 0; 1886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, cmd); 1906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 1916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 1926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->num_ssids) { 1946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *ssids; 1956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS); 1976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ssids == NULL) 1986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 1996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < params->num_ssids; i++) { 2006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID", 2016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssids[i].ssid, 2026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssids[i].ssid_len); 2036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, i + 1, params->ssids[i].ssid_len, 2046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssids[i].ssid)) 2056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, ssids); 208b70d0bbd90f638aa38da542e337c312309200e87Dmitry Shmidt } else { 209b70d0bbd90f638aa38da542e337c312309200e87Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested"); 2106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->extra_ies) { 2136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs", 2146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->extra_ies, params->extra_ies_len); 2156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len, 2166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->extra_ies)) 2176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->freqs) { 2216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *freqs; 2226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); 2236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (freqs == NULL) 2246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; params->freqs[i]; i++) { 2266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u " 2276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "MHz", params->freqs[i]); 2286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, i + 1, params->freqs[i])) 2296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, freqs); 2326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->filter_ssids); 2356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids = params->filter_ssids; 2366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_ssids = NULL; 2376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->num_filter_ssids = params->num_filter_ssids; 2386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->only_new_results) { 2406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH"); 2416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_FLUSH; 2426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->low_priority && drv->have_low_prio_scan) { 2456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 2466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY"); 2476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY; 2486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->mac_addr_rand) { 2516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 2526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR"); 2536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR; 2546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->mac_addr) { 2566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR, 2576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(params->mac_addr)); 2586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, 2596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->mac_addr)) 2606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->mac_addr_mask) { 2646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: " 2656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MACSTR, MAC2STR(params->mac_addr_mask)); 2666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN, 2676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->mac_addr_mask)) 2686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 272293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (params->duration) { 273293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (!(drv->capa.rrm_flags & 274293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) || 275293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt nla_put_u16(msg, NL80211_ATTR_MEASUREMENT_DURATION, 276293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt params->duration)) 277293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt goto fail; 278293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 279293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (params->duration_mandatory && 280293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt nla_put_flag(msg, 281293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY)) 282293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt goto fail; 283293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 284293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 2856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (scan_flags && 2866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags)) 2876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return msg; 2906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 2926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 2936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 2946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 2956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 2986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_scan - Request the driver to initiate scan 2996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @bss: Pointer to private driver data from wpa_driver_nl80211_init() 3006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @params: Scan parameters 3016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure 3026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_scan(struct i802_bss *bss, 3046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_scan_params *params) 3056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 3066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 3076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -1, timeout; 3086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg = NULL; 3096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request"); 3116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->scan_for_auth = 0; 3126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 313d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (TEST_FAIL()) 314d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 315d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_scan_common(bss, NL80211_CMD_TRIGGER_SCAN, params); 3176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 3186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 3196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->p2p_probe) { 3216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *rates; 3226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates"); 3246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES); 3266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rates == NULL) 3276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates 3316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * by masking out everything else apart from the OFDM rates 6, 3326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz 3336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * rates are left enabled. 3346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_BAND_2GHZ, 8, 3366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "\x0c\x12\x18\x24\x30\x48\x60\x6c")) 3376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, rates); 3396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) 3416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3449c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (params->bssid) { 3459c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: " 3469c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt MACSTR, MAC2STR(params->bssid)); 3479c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid)) 3489c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt goto fail; 3499c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt } 3509c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 3516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 3526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = NULL; 3536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 3546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " 3556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "(%s)", ret, strerror(-ret)); 3566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->hostapd && is_ap_interface(drv->nlmode)) { 3576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_iftype old_mode = drv->nlmode; 3586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * mac80211 does not allow scan requests in AP mode, so 3616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * try to do this in station mode. 3626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_set_mode( 3646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss, NL80211_IFTYPE_STATION)) 3656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_scan(bss, params)) { 3682f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_driver_nl80211_set_mode(bss, old_mode); 3696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Restore AP mode when processing scan results */ 3736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ap_scan_as_station = old_mode; 3746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = 0; 3756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else 3766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->scan_state = SCAN_REQUESTED; 3806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Not all drivers generate "scan completed" wireless event, so try to 3816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * read results after a timeout. */ 3826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt timeout = 10; 3836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->scan_complete_events) { 3846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * The driver seems to deliver events to notify when scan is 3866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * complete, so use longer timeout to avoid race conditions 3876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * with scanning and following association request. 3886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt timeout = 30; 3906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " 3926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "seconds", ret, timeout); 3936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); 3946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, 3956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv, drv->ctx); 396d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN; 3976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 3996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 4006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 4016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 4026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 404d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int 405d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtnl80211_sched_scan_add_scan_plans(struct wpa_driver_nl80211_data *drv, 406d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct nl_msg *msg, 407d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct wpa_driver_scan_params *params) 408d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 409d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct nlattr *plans; 410d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct sched_scan_plan *scan_plans = params->sched_scan_plans; 411d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt unsigned int i; 412d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 413d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt plans = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_PLANS); 414d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!plans) 415d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 416d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 417d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt for (i = 0; i < params->sched_scan_plans_num; i++) { 418d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct nlattr *plan = nla_nest_start(msg, i + 1); 419d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 420d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!plan) 421d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 422d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 423d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!scan_plans[i].interval || 424d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt scan_plans[i].interval > 425d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt drv->capa.max_sched_scan_plan_interval) { 426d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 427d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: sched scan plan no. %u: Invalid interval: %u", 428d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt i, scan_plans[i].interval); 429d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 430d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 431d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 432d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL, 433d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt scan_plans[i].interval)) 434d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 435d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 436d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (scan_plans[i].iterations > 437d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt drv->capa.max_sched_scan_plan_iterations) { 438d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 439d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: sched scan plan no. %u: Invalid number of iterations: %u", 440d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt i, scan_plans[i].iterations); 441d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 442d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 443d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 444d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (scan_plans[i].iterations && 445d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS, 446d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt scan_plans[i].iterations)) 447d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 448d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 449d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt nla_nest_end(msg, plan); 450d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 451d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt /* 452d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * All the scan plans must specify the number of iterations 453d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * except the last plan, which will run infinitely. So if the 454d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * number of iterations is not specified, this ought to be the 455d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * last scan plan. 456d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt */ 457d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!scan_plans[i].iterations) 458d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt break; 459d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 460d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 461d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (i != params->sched_scan_plans_num - 1) { 462d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 463d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: All sched scan plans but the last must specify number of iterations"); 464d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 465d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 466d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 467d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt nla_nest_end(msg, plans); 468d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return 0; 469d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 470d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 471d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 4726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 4736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan 4746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @priv: Pointer to private driver data from wpa_driver_nl80211_init() 4756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @params: Scan parameters 4766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure or if not supported 4776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 4786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_sched_scan(void *priv, 479d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct wpa_driver_scan_params *params) 4806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 4816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 4826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 4836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -1; 4846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 4856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 4866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request"); 4886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef ANDROID 4906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->capa.sched_scan_supported) 4916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return android_pno_start(bss, params); 4926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* ANDROID */ 4936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 494d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!params->sched_scan_plans_num || 495d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt params->sched_scan_plans_num > drv->capa.max_sched_scan_plans) { 496d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_ERROR, 497d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: Invalid number of sched scan plans: %u", 498d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt params->sched_scan_plans_num); 499d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 500d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 501d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 5026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_scan_common(bss, NL80211_CMD_START_SCHED_SCAN, params); 503d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!msg) 5046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 506d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (drv->capa.max_sched_scan_plan_iterations) { 507d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (nl80211_sched_scan_add_scan_plans(drv, msg, params)) 508d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt goto fail; 509d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } else { 510d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, 511d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt params->sched_scan_plans[0].interval * 1000)) 512d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt goto fail; 513d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 514d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 5156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((drv->num_filter_ssids && 5166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (int) drv->num_filter_ssids <= drv->capa.max_match_sets) || 5176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi) { 5186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *match_sets; 5196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH); 5206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (match_sets == NULL) 5216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < drv->num_filter_ssids; i++) { 5246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *match_set_ssid; 5256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, 5266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan filter SSID", 5276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid, 5286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid_len); 5296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt match_set_ssid = nla_nest_start(msg, i + 1); 5316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (match_set_ssid == NULL || 5326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID, 5336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid_len, 5346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid) || 5356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (params->filter_rssi && 5366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, 5376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, 5386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi))) 5396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, match_set_ssid); 5426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 5456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Due to backward compatibility code, newer kernels treat this 5466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * matchset (with only an RSSI filter) as the default for all 5476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * other matchsets, unless it's the only one, in which case the 5486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * matchset will actually allow all SSIDs above the RSSI. 5496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 5506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->filter_rssi) { 5516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *match_set_rssi; 5526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt match_set_rssi = nla_nest_start(msg, 0); 5536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (match_set_rssi == NULL || 5546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, 5556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi)) 5566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_MSGDUMP, 5586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan RSSI filter %d dBm", 5596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi); 5606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, match_set_rssi); 5616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, match_sets); 5646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 566ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (params->relative_rssi_set) { 567ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt struct nl80211_bss_select_rssi_adjust rssi_adjust; 568ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 569ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt os_memset(&rssi_adjust, 0, sizeof(rssi_adjust)); 570ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Relative RSSI: %d", 571ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt params->relative_rssi); 572ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI, 573ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt params->relative_rssi)) 574ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt goto fail; 575ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 576ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (params->relative_adjust_rssi) { 577ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt int pref_band_set = 1; 578ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 579ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt switch (params->relative_adjust_band) { 580ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt case WPA_SETBAND_5G: 581ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt rssi_adjust.band = NL80211_BAND_5GHZ; 582ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt break; 583ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt case WPA_SETBAND_2G: 584ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt rssi_adjust.band = NL80211_BAND_2GHZ; 585ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt break; 586ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt default: 587ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt pref_band_set = 0; 588ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt break; 589ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt } 590ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt rssi_adjust.delta = params->relative_adjust_rssi; 591ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 592ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (pref_band_set && 593ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, 594ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt sizeof(rssi_adjust), &rssi_adjust)) 595ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt goto fail; 596ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt } 597ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt } 598ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 599d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (params->sched_scan_start_delay && 600d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, 601d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt params->sched_scan_start_delay)) 602d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt goto fail; 603d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 6046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 6056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* TODO: if we get an error here, we should fall back to normal scan */ 6076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = NULL; 6096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 6106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: " 6116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "ret=%d (%s)", ret, strerror(-ret)); 6126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 6136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 6146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 615d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d)", ret); 6166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 6186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 6196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 6206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 6216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 6246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan 6256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @priv: Pointer to private driver data from wpa_driver_nl80211_init() 6266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure or if not supported 6276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 6286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_stop_sched_scan(void *priv) 6296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 6306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 6316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 6326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 6336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 6346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef ANDROID 6366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->capa.sched_scan_supported) 6376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return android_pno_stop(bss); 6386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* ANDROID */ 6396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN); 6416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 6426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 6436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 6446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan stop failed: ret=%d (%s)", 6456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 6466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 6476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 6486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan stop sent"); 6496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 6506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 6526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 6536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv, 6566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ie, size_t ie_len) 6576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 6586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ssid; 6596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 6606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->filter_ssids == NULL) 6626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 6636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ssid = get_ie(ie, ie_len, WLAN_EID_SSID); 6656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ssid == NULL) 6666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 1; 6676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < drv->num_filter_ssids; i++) { 6696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ssid[1] == drv->filter_ssids[i].ssid_len && 6706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) == 6716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0) 6726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 6736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 6746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 1; 6766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 6776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 679abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic struct wpa_scan_res * 680abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtnl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv, 681abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg) 6826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 6836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 6846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 6856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *bss[NL80211_BSS_MAX + 1]; 6866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { 6876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, 6886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, 6896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_TSF] = { .type = NLA_U64 }, 6906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, 6916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, 6926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, 6936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, 6946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, 6956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_STATUS] = { .type = NLA_U32 }, 6966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 }, 6976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC }, 698293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt [NL80211_BSS_PARENT_TSF] = { .type = NLA_U64 }, 699293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt [NL80211_BSS_PARENT_BSSID] = { .type = NLA_UNSPEC }, 700d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt [NL80211_BSS_LAST_SEEN_BOOTTIME] = { .type = NLA_U64 }, 7016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 7026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_scan_res *r; 7036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ie, *beacon_ie; 7046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t ie_len, beacon_ie_len; 7056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 *pos; 7066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 7086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 7096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_BSS]) 710abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], 7126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss_policy)) 713abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { 7156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 7166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 7176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 7186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie = NULL; 7196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie_len = 0; 7206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_BEACON_IES]) { 7226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]); 7236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]); 7246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 7256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie = NULL; 7266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie_len = 0; 7276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 729abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (nl80211_scan_filtered(drv, ie ? ie : beacon_ie, 7306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie ? ie_len : beacon_ie_len)) 731abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len); 7346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (r == NULL) 735abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_BSSID]) 7376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]), 7386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ETH_ALEN); 7396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_FREQUENCY]) 7406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); 7416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_BEACON_INTERVAL]) 7426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]); 7436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_CAPABILITY]) 7446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); 7456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_NOISE_INVALID; 7466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_SIGNAL_MBM]) { 7476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); 7486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->level /= 100; /* mBm to dBm */ 7496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID; 7506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) { 7516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); 7526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_QUAL_INVALID; 7536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else 7546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID; 7556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_TSF]) 7566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]); 757f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari if (bss[NL80211_BSS_BEACON_TSF]) { 758f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari u64 tsf = nla_get_u64(bss[NL80211_BSS_BEACON_TSF]); 759f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari if (tsf > r->tsf) 760f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari r->tsf = tsf; 761f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari } 7626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_SEEN_MS_AGO]) 7636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]); 764d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (bss[NL80211_BSS_LAST_SEEN_BOOTTIME]) { 765d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt u64 boottime; 766d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt struct timespec ts; 767d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 768d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifndef CLOCK_BOOTTIME 769d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#define CLOCK_BOOTTIME 7 770d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif 771d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) { 772d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /* Use more accurate boottime information to update the 773d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * scan result age since the driver reports this and 774d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * CLOCK_BOOTTIME is available. */ 775d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt boottime = nla_get_u64( 776d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt bss[NL80211_BSS_LAST_SEEN_BOOTTIME]); 777d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt r->age = ((u64) ts.tv_sec * 1000000000 + 778d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ts.tv_nsec - boottime) / 1000000; 779d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 780d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 7816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->ie_len = ie_len; 7826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos = (u8 *) (r + 1); 7836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ie) { 7846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(pos, ie, ie_len); 7856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos += ie_len; 7866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->beacon_ie_len = beacon_ie_len; 7886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (beacon_ie) 7896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(pos, beacon_ie, beacon_ie_len); 7906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_STATUS]) { 7926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_bss_status status; 7936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt status = nla_get_u32(bss[NL80211_BSS_STATUS]); 7946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (status) { 7956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case NL80211_BSS_STATUS_ASSOCIATED: 7966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_ASSOCIATED; 7976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 7986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 7996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 8006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 803293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (bss[NL80211_BSS_PARENT_TSF] && bss[NL80211_BSS_PARENT_BSSID]) { 804293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt r->parent_tsf = nla_get_u64(bss[NL80211_BSS_PARENT_TSF]); 805293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt os_memcpy(r->tsf_bssid, nla_data(bss[NL80211_BSS_PARENT_BSSID]), 806293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt ETH_ALEN); 807293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 808293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 809abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return r; 810abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 8116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 813abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstruct nl80211_bss_info_arg { 814abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 815abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_results *res; 816abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}; 8176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 818abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int bss_info_handler(struct nl_msg *msg, void *arg) 819abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 820abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_bss_info_arg *_arg = arg; 821abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_results *res = _arg->res; 822abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res **tmp; 823abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res *r; 824abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 825abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt r = nl80211_parse_bss_info(_arg->drv, msg); 826abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!r) 8276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 8286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 829abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!res) { 830abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_free(r); 831abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_SKIP; 832abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 8336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tmp = os_realloc_array(res->res, res->num + 1, 8346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sizeof(struct wpa_scan_res *)); 8356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (tmp == NULL) { 8366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(r); 8376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 8386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tmp[res->num++] = r; 8406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res->res = tmp; 8416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 8436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void clear_state_mismatch(struct wpa_driver_nl80211_data *drv, 8476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr) 8486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 8496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { 8506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Clear possible state " 8516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "mismatch (" MACSTR ")", MAC2STR(addr)); 8526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_mlme(drv, addr, 8536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_DEAUTHENTICATE, 8546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID, 1); 8556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 859abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic void nl80211_check_bss_status(struct wpa_driver_nl80211_data *drv, 860abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res *r) 861abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 862abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!(r->flags & WPA_SCAN_ASSOCIATED)) 863abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return; 864abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 865abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan results indicate BSS status with " 866abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt MACSTR " as associated", MAC2STR(r->bssid)); 867abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (is_sta_interface(drv->nlmode) && !drv->associated) { 868abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, 869abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt "nl80211: Local state (not associated) does not match with BSS state"); 870abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt clear_state_mismatch(drv, r->bssid); 871abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } else if (is_sta_interface(drv->nlmode) && 872abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_memcmp(drv->bssid, r->bssid, ETH_ALEN) != 0) { 873abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, 874abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt "nl80211: Local state (associated with " MACSTR 875abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ") does not match with BSS state", 876abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt MAC2STR(drv->bssid)); 877abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt clear_state_mismatch(drv, r->bssid); 878abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt clear_state_mismatch(drv, drv->bssid); 879abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 880abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 881abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 882abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 8836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_check_bss_status( 8846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res) 8856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 8866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 8876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 888abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt for (i = 0; i < res->num; i++) 889abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nl80211_check_bss_status(drv, res->res[i]); 890abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 891abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 892abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 893abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic void nl80211_update_scan_res_noise(struct wpa_scan_res *res, 894abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_noise_info *info) 895abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 896abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt unsigned int i; 897abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 898abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt for (i = 0; res && i < info->count; i++) { 899abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if ((int) info->freq[i] != res->freq || 900abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt !(res->flags & WPA_SCAN_NOISE_INVALID)) 901abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt continue; 902abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt res->noise = info->noise[i]; 903abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt res->flags &= ~WPA_SCAN_NOISE_INVALID; 9046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 9056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 9066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct wpa_scan_results * 9096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtnl80211_get_scan_results(struct wpa_driver_nl80211_data *drv) 9106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 9116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 9126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_scan_results *res; 9136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 9146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl80211_bss_info_arg arg; 9156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = os_zalloc(sizeof(*res)); 9176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res == NULL) 9186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 9196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, 9206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_GET_SCAN))) { 9216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_scan_results_free(res); 9226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 9236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 9246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt arg.drv = drv; 9266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt arg.res = res; 9276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); 9286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret == 0) { 929abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_noise_info info; 930abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 9316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu " 9326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "BSSes)", (unsigned long) res->num); 933abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (nl80211_get_noise_for_scan_results(drv, &info) == 0) { 934abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt size_t i; 935abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 936abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt for (i = 0; i < res->num; ++i) 937abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nl80211_update_scan_res_noise(res->res[i], 938abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt &info); 939abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 9406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return res; 9416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 9426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " 9436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "(%s)", ret, strerror(-ret)); 9446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_scan_results_free(res); 9456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 9466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 9476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 9506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results 9516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_nl80211_init() 9526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: Scan results on success, -1 on failure 9536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 9546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv) 9556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 9566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 9576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 9586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_scan_results *res; 9596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = nl80211_get_scan_results(drv); 9616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res) 9626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_check_bss_status(drv, res); 9636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return res; 9646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 9656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 967abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstruct nl80211_dump_scan_ctx { 968abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 969abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt int idx; 970abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}; 971abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 972abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int nl80211_dump_scan_handler(struct nl_msg *msg, void *arg) 9736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 974abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_dump_scan_ctx *ctx = arg; 975abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res *r; 9766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 977abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt r = nl80211_parse_bss_info(ctx->drv, msg); 978abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!r) 979abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_SKIP; 980abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s", 981abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx->idx, MAC2STR(r->bssid), r->freq, 982abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : ""); 983abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx->idx++; 984abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_free(r); 985abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_SKIP; 986abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 9876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 989abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtvoid nl80211_dump_scan(struct wpa_driver_nl80211_data *drv) 990abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 991abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg; 992abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_dump_scan_ctx ctx; 993abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 994abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan result dump"); 995abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx.drv = drv; 996abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx.idx = 0; 997abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, NL80211_CMD_GET_SCAN); 998abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (msg) 999abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx); 10006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 1001d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1002d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1003abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtint wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie) 1004d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1005d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct i802_bss *bss = priv; 1006abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 1007d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 1008d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1009abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt /* 1010abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * If scan_cookie is zero, a normal scan through kernel (cfg80211) 1011abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * was triggered, hence abort the cfg80211 scan instead of the vendor 1012abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * scan. 1013abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt */ 1014abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (drv->scan_vendor_cmd_avail && scan_cookie) 1015abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return nl80211_abort_vendor_scan(drv, scan_cookie); 1016abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 1017abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return nl80211_abort_scan(bss); 1018d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1019d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1020d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1021d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 1022d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1023d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int scan_cookie_handler(struct nl_msg *msg, void *arg) 1024d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 1025d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 1026d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 1027d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u64 *cookie = arg; 1028d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1029d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 1030d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 1031d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1032d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (tb[NL80211_ATTR_VENDOR_DATA]) { 1033d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *nl_vendor = tb[NL80211_ATTR_VENDOR_DATA]; 1034d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1]; 1035d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1036d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_SCAN_MAX, 1037d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_data(nl_vendor), nla_len(nl_vendor), NULL); 1038d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1039d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]) 1040d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt *cookie = nla_get_u64( 1041d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]); 1042d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1043d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1044d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return NL_SKIP; 1045d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 1046d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1047d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1048d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/** 1049d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * wpa_driver_nl80211_vendor_scan - Request the driver to initiate a vendor scan 1050d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @bss: Pointer to private driver data from wpa_driver_nl80211_init() 1051d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @params: Scan parameters 1052d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Returns: 0 on success, -1 on failure 1053d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 1054d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint wpa_driver_nl80211_vendor_scan(struct i802_bss *bss, 1055d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_driver_scan_params *params) 1056d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 1057d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 1058d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nl_msg *msg = NULL; 1059d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *attr; 1060d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt size_t i; 1061d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u32 scan_flags = 0; 1062d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt int ret = -1; 1063d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u64 cookie = 0; 1064d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1065d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: vendor scan request"); 1066d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->scan_for_auth = 0; 1067d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1068d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 1069d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 1070d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 1071d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) ) 1072d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1073d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1074d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); 1075d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (attr == NULL) 1076d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1077d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1078d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->num_ssids) { 1079d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *ssids; 1080d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1081d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ssids = nla_nest_start(msg, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS); 1082d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ssids == NULL) 1083d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1084d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt for (i = 0; i < params->num_ssids; i++) { 1085d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID", 1086d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->ssids[i].ssid, 1087d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->ssids[i].ssid_len); 1088d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, i + 1, params->ssids[i].ssid_len, 1089d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->ssids[i].ssid)) 1090d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1091d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1092d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, ssids); 1093d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1094d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1095d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->extra_ies) { 1096d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs", 1097d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->extra_ies, params->extra_ies_len); 1098d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_IE, 1099d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->extra_ies_len, params->extra_ies)) 1100d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1101d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1102d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1103d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->freqs) { 1104d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *freqs; 1105d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1106d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt freqs = nla_nest_start(msg, 1107d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES); 1108d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (freqs == NULL) 1109d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1110d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt for (i = 0; params->freqs[i]; i++) { 1111d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_MSGDUMP, 1112d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Scan frequency %u MHz", 1113d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->freqs[i]); 1114d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put_u32(msg, i + 1, params->freqs[i])) 1115d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1116d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1117d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, freqs); 1118d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1119d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1120d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_free(drv->filter_ssids); 1121d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->filter_ssids = params->filter_ssids; 1122d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->filter_ssids = NULL; 1123d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->num_filter_ssids = params->num_filter_ssids; 1124d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1125d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->low_priority && drv->have_low_prio_scan) { 1126d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1127d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY"); 1128d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY; 1129d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1130d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1131d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->mac_addr_rand) { 1132d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1133d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR"); 1134d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR; 1135d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1136d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->mac_addr) { 1137d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR, 1138d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt MAC2STR(params->mac_addr)); 1139d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC, 1140d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ETH_ALEN, params->mac_addr)) 1141d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1142d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1143d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1144d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->mac_addr_mask) { 1145d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: " 1146d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt MACSTR, MAC2STR(params->mac_addr_mask)); 1147d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK, 1148d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ETH_ALEN, params->mac_addr_mask)) 1149d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1150d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1151d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1152d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1153d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (scan_flags && 1154293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS, scan_flags)) 1155d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1156d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1157d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->p2p_probe) { 1158d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *rates; 1159d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1160d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates"); 1161d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1162d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt rates = nla_nest_start(msg, 1163d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES); 1164d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (rates == NULL) 1165d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1166d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1167d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* 1168d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates 1169d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * by masking out everything else apart from the OFDM rates 6, 1170d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz 1171d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * rates are left enabled. 1172d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 1173d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, NL80211_BAND_2GHZ, 8, 1174d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "\x0c\x12\x18\x24\x30\x48\x60\x6c")) 1175d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1176d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, rates); 1177d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1178d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE)) 1179d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1180d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1181d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1182293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (params->bssid) { 1183293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: " 1184293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt MACSTR, MAC2STR(params->bssid)); 1185293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_BSSID, ETH_ALEN, 1186293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt params->bssid)) 1187293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt goto fail; 1188293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 1189293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 1190d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, attr); 1191d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1192d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie); 1193d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt msg = NULL; 1194d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ret) { 1195d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1196d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Vendor scan trigger failed: ret=%d (%s)", 1197d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret, strerror(-ret)); 1198d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1199d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1200d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1201d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->vendor_scan_cookie = cookie; 1202d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->scan_state = SCAN_REQUESTED; 1203abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt /* Pass the cookie to the caller to help distinguish the scans. */ 1204abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt params->scan_cookie = cookie; 1205d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1206d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1207d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx", 1208d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret, (long long unsigned int) cookie); 1209d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); 1210d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout, 1211d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv, drv->ctx); 1212d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->last_scan_cmd = NL80211_CMD_VENDOR; 1213d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1214d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtfail: 1215d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nlmsg_free(msg); 1216d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return ret; 1217d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 1218d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 12197f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12207f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt/** 12217f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * nl80211_set_default_scan_ies - Set the scan default IEs to the driver 12227f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * @priv: Pointer to private driver data from wpa_driver_nl80211_init() 12237f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * @ies: Pointer to IEs buffer 12247f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * @ies_len: Length of IEs in bytes 12257f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * Returns: 0 on success, -1 on failure 12267f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt */ 12277f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidtint nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len) 12287f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt{ 12297f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct i802_bss *bss = priv; 12307f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 12317f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct nl_msg *msg = NULL; 12327f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct nlattr *attr; 12337f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt int ret = -1; 12347f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12357f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (!drv->set_wifi_conf_vendor_cmd_avail) 12367f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt return -1; 12377f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12387f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 12397f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 12407f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 12417f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION)) 12427f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12437f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12447f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); 12457f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (attr == NULL) 12467f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12477f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12487f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan default IEs", ies, ies_len); 12497f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES, 12507f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt ies_len, ies)) 12517f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12527f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12537f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nla_nest_end(msg, attr); 12547f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12557f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 12567f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt msg = NULL; 12577f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (ret) { 12587f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt wpa_printf(MSG_ERROR, 12597f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt "nl80211: Set scan default IEs failed: ret=%d (%s)", 12607f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt ret, strerror(-ret)); 12617f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12627f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt } 12637f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12647f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidtfail: 12657f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nlmsg_free(msg); 12667f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt return ret; 12677f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt} 12687f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 1269d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 1270