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