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" 136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include <netlink/genl/genl.h> 146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "utils/common.h" 166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "utils/eloop.h" 176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "common/ieee802_11_defs.h" 1857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "common/ieee802_11_common.h" 19d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "common/qca-vendor.h" 206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "driver_nl80211.h" 216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 23abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#define MAX_NL80211_NOISE_FREQS 50 24abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 25abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstruct nl80211_noise_info { 26abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt u32 freq[MAX_NL80211_NOISE_FREQS]; 27abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt s8 noise[MAX_NL80211_NOISE_FREQS]; 28abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt unsigned int count; 29abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}; 30abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int get_noise_for_scan_results(struct nl_msg *msg, void *arg) 326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1]; 366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = { 376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, 386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, 396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 40abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_noise_info *info = arg; 41abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 42abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (info->count >= MAX_NL80211_NOISE_FREQS) 43abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_STOP; 446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_SURVEY_INFO]) { 496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Survey data missing"); 506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX, 546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tb[NL80211_ATTR_SURVEY_INFO], 556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_policy)) { 566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested " 576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "attributes"); 586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_NOISE]) 626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) 656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt info->freq[info->count] = 68abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]); 69abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt info->noise[info->count] = 70abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]); 71abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt info->count++; 726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_get_noise_for_scan_results( 78abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv, struct nl80211_noise_info *info) 796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 82abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_memset(info, 0, sizeof(*info)); 836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); 84abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info); 85abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 86abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 87abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 88abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int nl80211_abort_scan(struct i802_bss *bss) 89abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 90abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt int ret; 91abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg; 92abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 93abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 94abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Abort scan"); 95abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN); 96abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 97abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (ret) { 98abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)", 99abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ret, strerror(-ret)); 100abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 101abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return ret; 102abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 103abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 104abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 105abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 106abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int nl80211_abort_vendor_scan(struct wpa_driver_nl80211_data *drv, 107abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt u64 scan_cookie) 108abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 109abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg; 110abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nlattr *params; 111abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt int ret; 112abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 113abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Abort vendor scan with cookie 0x%llx", 114abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt (long long unsigned int) scan_cookie); 115abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 116abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR); 117abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!msg || 118abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 119abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 120abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN) || 121abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || 122abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_put_u64(msg, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, scan_cookie)) 123abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt goto fail; 124abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 125abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nla_nest_end(msg, params); 126abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 127abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 128abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = NULL; 129abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (ret) { 130abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_INFO, 131abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt "nl80211: Aborting vendor scan with cookie 0x%llx failed: ret=%d (%s)", 132abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt (long long unsigned int) scan_cookie, ret, 133abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt strerror(-ret)); 134abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt goto fail; 135abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 136abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return 0; 137abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtfail: 138abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nlmsg_free(msg); 139abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return -1; 1406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 141abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 1426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 1456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion 1466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @eloop_ctx: Driver private data 1476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init() 1486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 1496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This function can be used as registered timeout when starting a scan to 1506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * generate a scan completed event if the driver does not report this. 1516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 1526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) 1536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 1546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = eloop_ctx; 1559c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1569c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it"); 157abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 158abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (drv->vendor_scan_cookie && 159092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0) 160abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return; 161abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 162abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!drv->vendor_scan_cookie && 163abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nl80211_abort_scan(drv->first_bss) == 0) 1649c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt return; 1659c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1669c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan"); 1679c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) { 1696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_set_mode(drv->first_bss, 1706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ap_scan_as_station); 1716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; 1726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 1739c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 1749c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results"); 1756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 1766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 1776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct nl_msg * 1806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtnl80211_scan_common(struct i802_bss *bss, u8 cmd, 1816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_scan_params *params) 1826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 1836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 1846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 1856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 1866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 scan_flags = 0; 1876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, cmd); 1896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 1906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 1916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->num_ssids) { 1936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *ssids; 1946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS); 1966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ssids == NULL) 1976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 1986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < params->num_ssids; i++) { 1996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID", 2006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssids[i].ssid, 2016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssids[i].ssid_len); 2026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, i + 1, params->ssids[i].ssid_len, 2036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssids[i].ssid)) 2046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, ssids); 207b70d0bbd90f638aa38da542e337c312309200e87Dmitry Shmidt } else { 208b70d0bbd90f638aa38da542e337c312309200e87Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested"); 2096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->extra_ies) { 2126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs", 2136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->extra_ies, params->extra_ies_len); 2146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len, 2156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->extra_ies)) 2166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->freqs) { 2206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *freqs; 2216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); 2226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (freqs == NULL) 2236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; params->freqs[i]; i++) { 2256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u " 2266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "MHz", params->freqs[i]); 2276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, i + 1, params->freqs[i])) 2286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, freqs); 2316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->filter_ssids); 2346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids = params->filter_ssids; 2356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_ssids = NULL; 2366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->num_filter_ssids = params->num_filter_ssids; 2376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->only_new_results) { 2396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH"); 2406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_FLUSH; 2416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->low_priority && drv->have_low_prio_scan) { 2446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 2456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY"); 2466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY; 2476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->mac_addr_rand) { 2506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 2516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR"); 2526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR; 2536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->mac_addr) { 2556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR, 2566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(params->mac_addr)); 2576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, 2586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->mac_addr)) 2596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->mac_addr_mask) { 2636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: " 2646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MACSTR, MAC2STR(params->mac_addr_mask)); 2656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN, 2666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->mac_addr_mask)) 2676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 271293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (params->duration) { 272293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (!(drv->capa.rrm_flags & 273293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) || 274293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt nla_put_u16(msg, NL80211_ATTR_MEASUREMENT_DURATION, 275293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt params->duration)) 276293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt goto fail; 277293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 278293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (params->duration_mandatory && 279293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt nla_put_flag(msg, 280293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY)) 281293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt goto fail; 282293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 283293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 2846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (scan_flags && 2856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags)) 2866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return msg; 2896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 2916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 2926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 2936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 2946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 2976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_scan - Request the driver to initiate scan 2986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @bss: Pointer to private driver data from wpa_driver_nl80211_init() 2996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @params: Scan parameters 3006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure 3016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_scan(struct i802_bss *bss, 3036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_scan_params *params) 3046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 3056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 3066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -1, timeout; 3076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg = NULL; 3086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request"); 3106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->scan_for_auth = 0; 3116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 312d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (TEST_FAIL()) 313d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 314d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_scan_common(bss, NL80211_CMD_TRIGGER_SCAN, params); 3166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 3176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 3186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->p2p_probe) { 3206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *rates; 3216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates"); 3236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES); 3256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rates == NULL) 3266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates 3306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * by masking out everything else apart from the OFDM rates 6, 3316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz 3326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * rates are left enabled. 3336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_BAND_2GHZ, 8, 3356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "\x0c\x12\x18\x24\x30\x48\x60\x6c")) 3366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, rates); 3386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) 3406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3439c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (params->bssid) { 3449c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: " 3459c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt MACSTR, MAC2STR(params->bssid)); 3469c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid)) 3479c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt goto fail; 3489c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt } 3499c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 3506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 3516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = NULL; 3526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 3536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " 3546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "(%s)", ret, strerror(-ret)); 3556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->hostapd && is_ap_interface(drv->nlmode)) { 3566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_iftype old_mode = drv->nlmode; 3576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * mac80211 does not allow scan requests in AP mode, so 3606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * try to do this in station mode. 3616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_set_mode( 3636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss, NL80211_IFTYPE_STATION)) 3646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_scan(bss, params)) { 3672f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_driver_nl80211_set_mode(bss, old_mode); 3686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Restore AP mode when processing scan results */ 3726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ap_scan_as_station = old_mode; 3736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = 0; 3746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else 3756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->scan_state = SCAN_REQUESTED; 3796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Not all drivers generate "scan completed" wireless event, so try to 3806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * read results after a timeout. */ 3816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt timeout = 10; 3826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->scan_complete_events) { 3836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * The driver seems to deliver events to notify when scan is 3856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * complete, so use longer timeout to avoid race conditions 3866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * with scanning and following association request. 3876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt timeout = 30; 3896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " 3916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "seconds", ret, timeout); 3926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); 3936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, 3946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv, drv->ctx); 395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN; 3966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 3986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 3996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 4006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 4016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 403d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int 404d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtnl80211_sched_scan_add_scan_plans(struct wpa_driver_nl80211_data *drv, 405d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct nl_msg *msg, 406d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct wpa_driver_scan_params *params) 407d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 408d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct nlattr *plans; 409d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct sched_scan_plan *scan_plans = params->sched_scan_plans; 410d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt unsigned int i; 411d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 412d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt plans = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_PLANS); 413d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!plans) 414d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 415d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 416d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt for (i = 0; i < params->sched_scan_plans_num; i++) { 417d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct nlattr *plan = nla_nest_start(msg, i + 1); 418d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 419d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!plan) 420d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 421d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 422d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!scan_plans[i].interval || 423d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt scan_plans[i].interval > 424d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt drv->capa.max_sched_scan_plan_interval) { 425d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 426d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: sched scan plan no. %u: Invalid interval: %u", 427d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt i, scan_plans[i].interval); 428d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 429d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 430d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 431d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL, 432d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt scan_plans[i].interval)) 433d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 434d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 435d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (scan_plans[i].iterations > 436d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt drv->capa.max_sched_scan_plan_iterations) { 437d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 438d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: sched scan plan no. %u: Invalid number of iterations: %u", 439d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt i, scan_plans[i].iterations); 440d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 441d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 442d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 443d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (scan_plans[i].iterations && 444d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS, 445d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt scan_plans[i].iterations)) 446d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 447d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 448d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt nla_nest_end(msg, plan); 449d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 450d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt /* 451d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * All the scan plans must specify the number of iterations 452d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * except the last plan, which will run infinitely. So if the 453d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * number of iterations is not specified, this ought to be the 454d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * last scan plan. 455d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt */ 456d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!scan_plans[i].iterations) 457d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt break; 458d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 459d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 460d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (i != params->sched_scan_plans_num - 1) { 461d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, 462d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: All sched scan plans but the last must specify number of iterations"); 463d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 464d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 465d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 466d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt nla_nest_end(msg, plans); 467d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return 0; 468d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 469d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 470d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 4716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 4726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan 4736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @priv: Pointer to private driver data from wpa_driver_nl80211_init() 4746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @params: Scan parameters 4756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure or if not supported 4766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 4776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_sched_scan(void *priv, 478d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct wpa_driver_scan_params *params) 4796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 4806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 4816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 4826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -1; 4836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 4846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 4856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request"); 4876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef ANDROID 4896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->capa.sched_scan_supported) 4906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return android_pno_start(bss, params); 4916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* ANDROID */ 4926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 493d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!params->sched_scan_plans_num || 494d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt params->sched_scan_plans_num > drv->capa.max_sched_scan_plans) { 495d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_ERROR, 496d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "nl80211: Invalid number of sched scan plans: %u", 497d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt params->sched_scan_plans_num); 498d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 499d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 500d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 5016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_scan_common(bss, NL80211_CMD_START_SCHED_SCAN, params); 502d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!msg) 5036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 505d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (drv->capa.max_sched_scan_plan_iterations) { 506d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (nl80211_sched_scan_add_scan_plans(drv, msg, params)) 507d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt goto fail; 508d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } else { 509d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, 510d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt params->sched_scan_plans[0].interval * 1000)) 511d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt goto fail; 512d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 513d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 5146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((drv->num_filter_ssids && 5156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (int) drv->num_filter_ssids <= drv->capa.max_match_sets) || 5166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi) { 5176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *match_sets; 5186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH); 5196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (match_sets == NULL) 5206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < drv->num_filter_ssids; i++) { 5236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *match_set_ssid; 5246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, 5256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan filter SSID", 5266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid, 5276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid_len); 5286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt match_set_ssid = nla_nest_start(msg, i + 1); 5306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (match_set_ssid == NULL || 5316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID, 5326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid_len, 5336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->filter_ssids[i].ssid) || 5346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (params->filter_rssi && 5356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, 5366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, 5376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi))) 5386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, match_set_ssid); 5416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 5446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Due to backward compatibility code, newer kernels treat this 5456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * matchset (with only an RSSI filter) as the default for all 5466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * other matchsets, unless it's the only one, in which case the 5476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * matchset will actually allow all SSIDs above the RSSI. 5486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 5496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->filter_rssi) { 5506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *match_set_rssi; 5516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt match_set_rssi = nla_nest_start(msg, 0); 5526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (match_set_rssi == NULL || 5536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, 5546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi)) 5556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 5566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_MSGDUMP, 5576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan RSSI filter %d dBm", 5586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->filter_rssi); 5596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, match_set_rssi); 5606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, match_sets); 5636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 565ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (params->relative_rssi_set) { 566ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt struct nl80211_bss_select_rssi_adjust rssi_adjust; 567ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 568ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt os_memset(&rssi_adjust, 0, sizeof(rssi_adjust)); 569ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Relative RSSI: %d", 570ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt params->relative_rssi); 571ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI, 572ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt params->relative_rssi)) 573ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt goto fail; 574ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 575ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (params->relative_adjust_rssi) { 576ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt int pref_band_set = 1; 577ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 578ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt switch (params->relative_adjust_band) { 579ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt case WPA_SETBAND_5G: 580ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt rssi_adjust.band = NL80211_BAND_5GHZ; 581ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt break; 582ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt case WPA_SETBAND_2G: 583ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt rssi_adjust.band = NL80211_BAND_2GHZ; 584ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt break; 585ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt default: 586ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt pref_band_set = 0; 587ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt break; 588ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt } 589ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt rssi_adjust.delta = params->relative_adjust_rssi; 590ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 591ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt if (pref_band_set && 592ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, 593ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt sizeof(rssi_adjust), &rssi_adjust)) 594ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt goto fail; 595ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt } 596ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt } 597ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 5986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 5996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* TODO: if we get an error here, we should fall back to normal scan */ 6016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = NULL; 6036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 6046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: " 6056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "ret=%d (%s)", ret, strerror(-ret)); 6066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 6076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 6086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 609d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d)", ret); 6106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 6126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 6136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 6146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 6156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 6186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan 6196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @priv: Pointer to private driver data from wpa_driver_nl80211_init() 6206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure or if not supported 6216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 6226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_stop_sched_scan(void *priv) 6236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 6246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 6256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 6266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 6276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 6286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef ANDROID 6306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->capa.sched_scan_supported) 6316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return android_pno_stop(bss); 6326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* ANDROID */ 6336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN); 6356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 6366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 6376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 6386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan stop failed: ret=%d (%s)", 6396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 6406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 6416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 6426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Sched scan stop sent"); 6436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 6446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 6466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 6476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv, 6506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ie, size_t ie_len) 6516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 6526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ssid; 6536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 6546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->filter_ssids == NULL) 6566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 6576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 65857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ssid = get_ie(ie, ie_len, WLAN_EID_SSID); 6596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ssid == NULL) 6606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 1; 6616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < drv->num_filter_ssids; i++) { 6636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ssid[1] == drv->filter_ssids[i].ssid_len && 6646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) == 6656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0) 6666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 6676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 6686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 1; 6706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 6716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 673abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic struct wpa_scan_res * 674abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtnl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv, 675abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg) 6766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 6776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 6786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 6796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *bss[NL80211_BSS_MAX + 1]; 6806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { 6816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, 6826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, 6836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_TSF] = { .type = NLA_U64 }, 6846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, 6856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, 6866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, 6876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, 6886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, 6896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_STATUS] = { .type = NLA_U32 }, 6906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 }, 6916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC }, 692293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt [NL80211_BSS_PARENT_TSF] = { .type = NLA_U64 }, 693293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt [NL80211_BSS_PARENT_BSSID] = { .type = NLA_UNSPEC }, 6946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 6956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_scan_res *r; 6966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ie, *beacon_ie; 6976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t ie_len, beacon_ie_len; 6986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 *pos; 6996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 7016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 7026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_BSS]) 703abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], 7056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss_policy)) 706abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { 7086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 7096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 7106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 7116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie = NULL; 7126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie_len = 0; 7136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_BEACON_IES]) { 7156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]); 7166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]); 7176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 7186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie = NULL; 7196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_ie_len = 0; 7206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 722abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (nl80211_scan_filtered(drv, ie ? ie : beacon_ie, 7236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ie ? ie_len : beacon_ie_len)) 724abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len); 7276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (r == NULL) 728abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NULL; 7296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_BSSID]) 7306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]), 7316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ETH_ALEN); 7326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_FREQUENCY]) 7336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); 7346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_BEACON_INTERVAL]) 7356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]); 7366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_CAPABILITY]) 7376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); 7386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_NOISE_INVALID; 7396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_SIGNAL_MBM]) { 7406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); 7416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->level /= 100; /* mBm to dBm */ 7426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID; 7436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) { 7446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); 7456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_QUAL_INVALID; 7466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else 7476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID; 7486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_TSF]) 7496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]); 750f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari if (bss[NL80211_BSS_BEACON_TSF]) { 751f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari u64 tsf = nla_get_u64(bss[NL80211_BSS_BEACON_TSF]); 752f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari if (tsf > r->tsf) 753f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari r->tsf = tsf; 754f8467ce3721b7154974a1f8a6e0dff54d4493f4dSrinivas Dasari } 7556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_SEEN_MS_AGO]) 7566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]); 7576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->ie_len = ie_len; 7586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos = (u8 *) (r + 1); 7596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ie) { 7606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(pos, ie, ie_len); 7616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos += ie_len; 7626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->beacon_ie_len = beacon_ie_len; 7646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (beacon_ie) 7656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(pos, beacon_ie, beacon_ie_len); 7666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss[NL80211_BSS_STATUS]) { 7686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_bss_status status; 7696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt status = nla_get_u32(bss[NL80211_BSS_STATUS]); 7706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (status) { 7716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case NL80211_BSS_STATUS_ASSOCIATED: 7726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt r->flags |= WPA_SCAN_ASSOCIATED; 7736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 7746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 7756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 7766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 779293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (bss[NL80211_BSS_PARENT_TSF] && bss[NL80211_BSS_PARENT_BSSID]) { 780293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt r->parent_tsf = nla_get_u64(bss[NL80211_BSS_PARENT_TSF]); 781293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt os_memcpy(r->tsf_bssid, nla_data(bss[NL80211_BSS_PARENT_BSSID]), 782293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt ETH_ALEN); 783293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 784293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 785abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return r; 786abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 7876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 789abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstruct nl80211_bss_info_arg { 790abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 791abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_results *res; 792abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}; 7936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 794abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int bss_info_handler(struct nl_msg *msg, void *arg) 795abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 796abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_bss_info_arg *_arg = arg; 797abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_results *res = _arg->res; 798abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res **tmp; 799abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res *r; 800abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 801abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt r = nl80211_parse_bss_info(_arg->drv, msg); 802abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!r) 8036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 8046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 805abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!res) { 806abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_free(r); 807abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_SKIP; 808abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 8096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tmp = os_realloc_array(res->res, res->num + 1, 8106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sizeof(struct wpa_scan_res *)); 8116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (tmp == NULL) { 8126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(r); 8136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 8146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tmp[res->num++] = r; 8166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res->res = tmp; 8176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 8196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void clear_state_mismatch(struct wpa_driver_nl80211_data *drv, 8236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr) 8246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 8256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { 8266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Clear possible state " 8276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "mismatch (" MACSTR ")", MAC2STR(addr)); 8286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_mlme(drv, addr, 8296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_DEAUTHENTICATE, 8306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID, 1); 8316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 835abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic void nl80211_check_bss_status(struct wpa_driver_nl80211_data *drv, 836abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res *r) 837abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 838abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!(r->flags & WPA_SCAN_ASSOCIATED)) 839abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return; 840abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 841abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan results indicate BSS status with " 842abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt MACSTR " as associated", MAC2STR(r->bssid)); 843abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (is_sta_interface(drv->nlmode) && !drv->associated) { 844abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, 845abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt "nl80211: Local state (not associated) does not match with BSS state"); 846abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt clear_state_mismatch(drv, r->bssid); 847abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } else if (is_sta_interface(drv->nlmode) && 848abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_memcmp(drv->bssid, r->bssid, ETH_ALEN) != 0) { 849abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, 850abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt "nl80211: Local state (associated with " MACSTR 851abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ") does not match with BSS state", 852abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt MAC2STR(drv->bssid)); 853abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt clear_state_mismatch(drv, r->bssid); 854abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt clear_state_mismatch(drv, drv->bssid); 855abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 856abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 857abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 858abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 8596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_check_bss_status( 8606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res) 8616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 8626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t i; 8636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 864abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt for (i = 0; i < res->num; i++) 865abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nl80211_check_bss_status(drv, res->res[i]); 866abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 867abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 868abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 869abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic void nl80211_update_scan_res_noise(struct wpa_scan_res *res, 870abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_noise_info *info) 871abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 872abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt unsigned int i; 873abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 874abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt for (i = 0; res && i < info->count; i++) { 875abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if ((int) info->freq[i] != res->freq || 876abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt !(res->flags & WPA_SCAN_NOISE_INVALID)) 877abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt continue; 878abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt res->noise = info->noise[i]; 879abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt res->flags &= ~WPA_SCAN_NOISE_INVALID; 8806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct wpa_scan_results * 8856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtnl80211_get_scan_results(struct wpa_driver_nl80211_data *drv) 8866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 8876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 8886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_scan_results *res; 8896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 8906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl80211_bss_info_arg arg; 8916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = os_zalloc(sizeof(*res)); 8936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res == NULL) 8946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 8956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, 8966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_GET_SCAN))) { 8976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_scan_results_free(res); 8986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 8996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 9006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt arg.drv = drv; 9026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt arg.res = res; 9036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); 9046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret == 0) { 905abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_noise_info info; 906abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 9076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu " 9086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "BSSes)", (unsigned long) res->num); 909abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (nl80211_get_noise_for_scan_results(drv, &info) == 0) { 910abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt size_t i; 911abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 912abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt for (i = 0; i < res->num; ++i) 913abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt nl80211_update_scan_res_noise(res->res[i], 914abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt &info); 915abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt } 9166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return res; 9176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 9186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " 9196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "(%s)", ret, strerror(-ret)); 9206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_scan_results_free(res); 9216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 9226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 9236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 9266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results 9276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_nl80211_init() 9286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: Scan results on success, -1 on failure 9296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 9306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv) 9316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 9326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 9336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 9346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_scan_results *res; 9356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = nl80211_get_scan_results(drv); 9376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res) 9386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_check_bss_status(drv, res); 9396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return res; 9406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 9416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 943abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstruct nl80211_dump_scan_ctx { 944abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 945abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt int idx; 946abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}; 947abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 948abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int nl80211_dump_scan_handler(struct nl_msg *msg, void *arg) 9496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 950abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_dump_scan_ctx *ctx = arg; 951abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct wpa_scan_res *r; 9526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 953abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt r = nl80211_parse_bss_info(ctx->drv, msg); 954abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (!r) 955abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_SKIP; 956abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s", 957abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx->idx, MAC2STR(r->bssid), r->freq, 958abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : ""); 959abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx->idx++; 960abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt os_free(r); 961abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return NL_SKIP; 962abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt} 9636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 9646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 965abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtvoid nl80211_dump_scan(struct wpa_driver_nl80211_data *drv) 966abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{ 967abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl_msg *msg; 968abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt struct nl80211_dump_scan_ctx ctx; 969abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt 970abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan result dump"); 971abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx.drv = drv; 972abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt ctx.idx = 0; 973abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, NL80211_CMD_GET_SCAN); 974abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (msg) 975abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx); 9766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 977d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 978d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 979abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtint wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie) 980d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 981d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct i802_bss *bss = priv; 982abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 983d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 984d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 985abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt /* 986abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * If scan_cookie is zero, a normal scan through kernel (cfg80211) 987abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * was triggered, hence abort the cfg80211 scan instead of the vendor 988abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * scan. 989abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt */ 990abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt if (drv->scan_vendor_cmd_avail && scan_cookie) 991abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return nl80211_abort_vendor_scan(drv, scan_cookie); 992abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 993abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt return nl80211_abort_scan(bss); 994d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 995d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 996d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 997d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_DRIVER_NL80211_QCA 998d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 999d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int scan_cookie_handler(struct nl_msg *msg, void *arg) 1000d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 1001d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 1002d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 1003d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u64 *cookie = arg; 1004d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1005d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 1006d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 1007d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1008d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (tb[NL80211_ATTR_VENDOR_DATA]) { 1009d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *nl_vendor = tb[NL80211_ATTR_VENDOR_DATA]; 1010d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1]; 1011d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1012d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_SCAN_MAX, 1013d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_data(nl_vendor), nla_len(nl_vendor), NULL); 1014d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1015d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]) 1016d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt *cookie = nla_get_u64( 1017d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]); 1018d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1019d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1020d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return NL_SKIP; 1021d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 1022d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1023d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1024d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/** 1025d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * wpa_driver_nl80211_vendor_scan - Request the driver to initiate a vendor scan 1026d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @bss: Pointer to private driver data from wpa_driver_nl80211_init() 1027d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @params: Scan parameters 1028d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Returns: 0 on success, -1 on failure 1029d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 1030d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint wpa_driver_nl80211_vendor_scan(struct i802_bss *bss, 1031d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_driver_scan_params *params) 1032d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 1033d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 1034d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nl_msg *msg = NULL; 1035d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *attr; 1036d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt size_t i; 1037d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u32 scan_flags = 0; 1038d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt int ret = -1; 1039d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u64 cookie = 0; 1040d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1041d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: vendor scan request"); 1042d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->scan_for_auth = 0; 1043d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1044d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 1045d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 1046d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 1047d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) ) 1048d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1049d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1050d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); 1051d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (attr == NULL) 1052d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1053d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1054d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->num_ssids) { 1055d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *ssids; 1056d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1057d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ssids = nla_nest_start(msg, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS); 1058d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ssids == NULL) 1059d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1060d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt for (i = 0; i < params->num_ssids; i++) { 1061d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID", 1062d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->ssids[i].ssid, 1063d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->ssids[i].ssid_len); 1064d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, i + 1, params->ssids[i].ssid_len, 1065d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->ssids[i].ssid)) 1066d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1067d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1068d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, ssids); 1069d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1070d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1071d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->extra_ies) { 1072d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs", 1073d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->extra_ies, params->extra_ies_len); 1074d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_IE, 1075d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->extra_ies_len, params->extra_ies)) 1076d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1077d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1078d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1079d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->freqs) { 1080d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *freqs; 1081d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1082d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt freqs = nla_nest_start(msg, 1083d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES); 1084d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (freqs == NULL) 1085d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1086d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt for (i = 0; params->freqs[i]; i++) { 1087d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_MSGDUMP, 1088d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Scan frequency %u MHz", 1089d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->freqs[i]); 1090d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put_u32(msg, i + 1, params->freqs[i])) 1091d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1092d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1093d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, freqs); 1094d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1095d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1096d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_free(drv->filter_ssids); 1097d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->filter_ssids = params->filter_ssids; 1098d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt params->filter_ssids = NULL; 1099d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->num_filter_ssids = params->num_filter_ssids; 1100d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1101d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->low_priority && drv->have_low_prio_scan) { 1102d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1103d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY"); 1104d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY; 1105d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1106d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1107d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->mac_addr_rand) { 1108d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1109d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR"); 1110d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR; 1111d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1112d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->mac_addr) { 1113d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR, 1114d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt MAC2STR(params->mac_addr)); 1115d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC, 1116d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ETH_ALEN, params->mac_addr)) 1117d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1118d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1119d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1120d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->mac_addr_mask) { 1121d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: " 1122d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt MACSTR, MAC2STR(params->mac_addr_mask)); 1123d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK, 1124d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ETH_ALEN, params->mac_addr_mask)) 1125d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1126d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1127d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1128d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1129d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (scan_flags && 1130293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS, scan_flags)) 1131d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1132d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1133d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (params->p2p_probe) { 1134d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct nlattr *rates; 1135d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1136d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates"); 1137d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1138d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt rates = nla_nest_start(msg, 1139d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES); 1140d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (rates == NULL) 1141d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1142d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1143d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* 1144d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates 1145d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * by masking out everything else apart from the OFDM rates 6, 1146d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz 1147d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * rates are left enabled. 1148d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 1149d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put(msg, NL80211_BAND_2GHZ, 8, 1150d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "\x0c\x12\x18\x24\x30\x48\x60\x6c")) 1151d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1152d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, rates); 1153d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1154d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE)) 1155d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1156d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1157d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1158293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (params->bssid) { 1159293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: " 1160293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt MACSTR, MAC2STR(params->bssid)); 1161293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_BSSID, ETH_ALEN, 1162293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt params->bssid)) 1163293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt goto fail; 1164293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 1165293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 1166d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nla_nest_end(msg, attr); 1167d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1168d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie); 1169d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt msg = NULL; 1170d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ret) { 1171d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1172d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Vendor scan trigger failed: ret=%d (%s)", 1173d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret, strerror(-ret)); 1174d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto fail; 1175d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1176d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1177d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->vendor_scan_cookie = cookie; 1178d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->scan_state = SCAN_REQUESTED; 1179abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt /* Pass the cookie to the caller to help distinguish the scans. */ 1180abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt params->scan_cookie = cookie; 1181d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1182d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1183d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx", 1184d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret, (long long unsigned int) cookie); 1185d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); 1186d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout, 1187d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv, drv->ctx); 1188d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt drv->last_scan_cmd = NL80211_CMD_VENDOR; 1189d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1190d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtfail: 1191d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt nlmsg_free(msg); 1192d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return ret; 1193d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 1194d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 11957f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 11967f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt/** 11977f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * nl80211_set_default_scan_ies - Set the scan default IEs to the driver 11987f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * @priv: Pointer to private driver data from wpa_driver_nl80211_init() 11997f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * @ies: Pointer to IEs buffer 12007f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * @ies_len: Length of IEs in bytes 12017f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * Returns: 0 on success, -1 on failure 12027f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt */ 12037f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidtint nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len) 12047f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt{ 12057f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct i802_bss *bss = priv; 12067f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 12077f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct nl_msg *msg = NULL; 12087f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt struct nlattr *attr; 12097f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt int ret = -1; 12107f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12117f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (!drv->set_wifi_conf_vendor_cmd_avail) 12127f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt return -1; 12137f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12147f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 12157f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 12167f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 12177f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION)) 12187f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12197f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12207f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); 12217f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (attr == NULL) 12227f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12237f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12247f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan default IEs", ies, ies_len); 12257f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES, 12267f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt ies_len, ies)) 12277f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12287f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12297f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nla_nest_end(msg, attr); 12307f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12317f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 12327f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt msg = NULL; 12337f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt if (ret) { 12347f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt wpa_printf(MSG_ERROR, 12357f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt "nl80211: Set scan default IEs failed: ret=%d (%s)", 12367f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt ret, strerror(-ret)); 12377f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt goto fail; 12387f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt } 12397f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 12407f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidtfail: 12417f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt nlmsg_free(msg); 12427f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt return ret; 12437f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt} 12447f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 1245d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_DRIVER_NL80211_QCA */ 1246