mlme.c 173.4 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3
/*
 * BSS client mode implementation
4
 * Copyright 2003-2008, Jouni Malinen <j@w1.fi>
5 6 7 8
 * Copyright 2004, Instant802 Networks, Inc.
 * Copyright 2005, Devicescape Software, Inc.
 * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9
 * Copyright 2013-2014  Intel Mobile Communications GmbH
10
 * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
11
 * Copyright (C) 2018 - 2021 Intel Corporation
12 13
 */

14
#include <linux/delay.h>
15
#include <linux/fips.h>
16 17 18 19
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
20
#include <linux/moduleparam.h>
21
#include <linux/rtnetlink.h>
22
#include <linux/crc32.h>
23
#include <linux/slab.h>
24
#include <linux/export.h>
25
#include <net/mac80211.h>
26
#include <asm/unaligned.h>
J
Johannes Berg 已提交
27

28
#include "ieee80211_i.h"
29
#include "driver-ops.h"
J
Johannes Berg 已提交
30 31
#include "rate.h"
#include "led.h"
32
#include "fils_aead.h"
33

34
#define IEEE80211_AUTH_TIMEOUT		(HZ / 5)
35
#define IEEE80211_AUTH_TIMEOUT_LONG	(HZ / 2)
36
#define IEEE80211_AUTH_TIMEOUT_SHORT	(HZ / 10)
37
#define IEEE80211_AUTH_TIMEOUT_SAE	(HZ * 2)
38 39 40
#define IEEE80211_AUTH_MAX_TRIES	3
#define IEEE80211_AUTH_WAIT_ASSOC	(HZ * 5)
#define IEEE80211_ASSOC_TIMEOUT		(HZ / 5)
41
#define IEEE80211_ASSOC_TIMEOUT_LONG	(HZ / 2)
42 43
#define IEEE80211_ASSOC_TIMEOUT_SHORT	(HZ / 10)
#define IEEE80211_ASSOC_MAX_TRIES	3
J
Johannes Berg 已提交
44

45 46 47 48 49 50 51 52 53
static int max_nullfunc_tries = 2;
module_param(max_nullfunc_tries, int, 0644);
MODULE_PARM_DESC(max_nullfunc_tries,
		 "Maximum nullfunc tx tries before disconnecting (reason 4).");

static int max_probe_tries = 5;
module_param(max_probe_tries, int, 0644);
MODULE_PARM_DESC(max_probe_tries,
		 "Maximum probe tries before disconnecting (reason 4).");
J
Johannes Berg 已提交
54 55

/*
56 57 58 59 60 61
 * Beacon loss timeout is calculated as N frames times the
 * advertised beacon interval.  This may need to be somewhat
 * higher than what hardware might detect to account for
 * delays in the host processing frames. But since we also
 * probe on beacon miss before declaring the connection lost
 * default to what we want.
J
Johannes Berg 已提交
62
 */
63 64 65 66
static int beacon_loss_count = 7;
module_param(beacon_loss_count, int, 0644);
MODULE_PARM_DESC(beacon_loss_count,
		 "Number of beacon intervals before we decide beacon was lost.");
67

J
Johannes Berg 已提交
68 69 70 71
/*
 * Time the connection can be idle before we probe
 * it to see if we can still talk to the AP.
 */
72
#define IEEE80211_CONNECTION_IDLE_TIME	(30 * HZ)
J
Johannes Berg 已提交
73 74 75 76 77
/*
 * Time we wait for a probe response after sending
 * a probe request because of beacon loss or for
 * checking the connection still works.
 */
78 79 80 81 82
static int probe_wait_ms = 500;
module_param(probe_wait_ms, int, 0644);
MODULE_PARM_DESC(probe_wait_ms,
		 "Maximum time(ms) to wait for probe response"
		 " before disconnecting (reason 4).");
83

84 85 86 87 88 89
/*
 * How many Beacon frames need to have been used in average signal strength
 * before starting to indicate signal change events.
 */
#define IEEE80211_SIGNAL_AVE_MIN_COUNT	4

J
Johannes Berg 已提交
90 91 92 93 94 95 96 97 98 99
/*
 * We can have multiple work items (and connection probing)
 * scheduling this timer, but we need to take care to only
 * reschedule it when it should fire _earlier_ than it was
 * asked for before, or if it's not pending right now. This
 * function ensures that. Note that it then is required to
 * run this function for all timeouts after the first one
 * has happened -- the work that runs from this timer will
 * do that.
 */
100 101
static void run_again(struct ieee80211_sub_if_data *sdata,
		      unsigned long timeout)
J
Johannes Berg 已提交
102
{
103
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
104

105 106 107
	if (!timer_pending(&sdata->u.mgd.timer) ||
	    time_before(timeout, sdata->u.mgd.timer.expires))
		mod_timer(&sdata->u.mgd.timer, timeout);
J
Johannes Berg 已提交
108 109
}

110
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
111
{
112
	if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
J
Johannes Berg 已提交
113 114
		return;

115
	if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
116 117
		return;

J
Johannes Berg 已提交
118
	mod_timer(&sdata->u.mgd.bcn_mon_timer,
119
		  round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout));
J
Johannes Berg 已提交
120 121
}

122 123
void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
{
124 125
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

126
	if (unlikely(!ifmgd->associated))
127 128
		return;

129 130
	if (ifmgd->probe_send_count)
		ifmgd->probe_send_count = 0;
131

132
	if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
133 134
		return;

135
	mod_timer(&ifmgd->conn_mon_timer,
136 137 138
		  round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
}

139
static int ecw2cw(int ecw)
J
Johannes Berg 已提交
140
{
141
	return (1 << ecw) - 1;
J
Johannes Berg 已提交
142 143
}

144 145 146 147
static u32
ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_supported_band *sband,
			     struct ieee80211_channel *channel,
148
			     u32 vht_cap_info,
149 150
			     const struct ieee80211_ht_operation *ht_oper,
			     const struct ieee80211_vht_operation *vht_oper,
L
Luca Coelho 已提交
151
			     const struct ieee80211_he_operation *he_oper,
152
			     const struct ieee80211_s1g_oper_ie *s1g_oper,
153
			     struct cfg80211_chan_def *chandef, bool tracking)
154
{
155
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
156
	struct cfg80211_chan_def vht_chandef;
157
	struct ieee80211_sta_ht_cap sta_ht_cap;
158 159
	u32 ht_cfreq, ret;

160
	memset(chandef, 0, sizeof(struct cfg80211_chan_def));
161 162 163
	chandef->chan = channel;
	chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
	chandef->center_freq1 = channel->center_freq;
164
	chandef->freq1_offset = channel->freq_offset;
165

166 167 168 169 170
	if (channel->band == NL80211_BAND_6GHZ) {
		if (!ieee80211_chandef_he_6ghz_oper(sdata, he_oper, chandef))
			ret = IEEE80211_STA_DISABLE_HT |
			      IEEE80211_STA_DISABLE_VHT |
			      IEEE80211_STA_DISABLE_HE;
171 172
		else
			ret = 0;
173 174
		vht_chandef = *chandef;
		goto out;
175 176 177 178 179 180
	} else if (sband->band == NL80211_BAND_S1GHZ) {
		if (!ieee80211_chandef_s1g_oper(s1g_oper, chandef)) {
			sdata_info(sdata,
				   "Missing S1G Operation Element? Trying operating == primary\n");
			chandef->width = ieee80211_s1g_channel_width(channel);
		}
181

182 183 184 185 186 187 188
		ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_40MHZ |
		      IEEE80211_STA_DISABLE_VHT |
		      IEEE80211_STA_DISABLE_80P80MHZ |
		      IEEE80211_STA_DISABLE_160MHZ;
		goto out;
	}

189 190 191
	memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
	ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);

192
	if (!ht_oper || !sta_ht_cap.ht_supported) {
193 194 195
		ret = IEEE80211_STA_DISABLE_HT |
		      IEEE80211_STA_DISABLE_VHT |
		      IEEE80211_STA_DISABLE_HE;
196 197 198 199 200 201 202 203
		goto out;
	}

	chandef->width = NL80211_CHAN_WIDTH_20;

	ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
						  channel->band);
	/* check that channel matches the right operating channel */
204
	if (!tracking && channel->center_freq != ht_cfreq) {
205 206 207 208 209 210 211
		/*
		 * It's possible that some APs are confused here;
		 * Netgear WNDR3700 sometimes reports 4 higher than
		 * the actual channel in association responses, but
		 * since we look at probe response/beacon data here
		 * it should be OK.
		 */
212 213 214 215
		sdata_info(sdata,
			   "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
			   channel->center_freq, ht_cfreq,
			   ht_oper->primary_chan, channel->band);
216 217 218
		ret = IEEE80211_STA_DISABLE_HT |
		      IEEE80211_STA_DISABLE_VHT |
		      IEEE80211_STA_DISABLE_HE;
219 220 221 222
		goto out;
	}

	/* check 40 MHz support, if we have it */
223
	if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
224
		ieee80211_chandef_ht_oper(ht_oper, chandef);
225 226 227
	} else {
		/* 40 MHz (and 80 MHz) must be supported for VHT */
		ret = IEEE80211_STA_DISABLE_VHT;
228 229
		/* also mark 40 MHz disabled */
		ret |= IEEE80211_STA_DISABLE_40MHZ;
230 231 232 233 234 235 236 237
		goto out;
	}

	if (!vht_oper || !sband->vht_cap.vht_supported) {
		ret = IEEE80211_STA_DISABLE_VHT;
		goto out;
	}

238
	vht_chandef = *chandef;
L
Luca Coelho 已提交
239 240 241 242 243 244 245 246 247 248 249 250
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && he_oper &&
	    (le32_to_cpu(he_oper->he_oper_params) &
	     IEEE80211_HE_OPERATION_VHT_OPER_INFO)) {
		struct ieee80211_vht_operation he_oper_vht_cap;

		/*
		 * Set only first 3 bytes (other 2 aren't used in
		 * ieee80211_chandef_vht_oper() anyway)
		 */
		memcpy(&he_oper_vht_cap, he_oper->optional, 3);
		he_oper_vht_cap.basic_mcs_set = cpu_to_le16(0);

251
		if (!ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info,
252
						&he_oper_vht_cap, ht_oper,
L
Luca Coelho 已提交
253 254 255 256 257 258 259
						&vht_chandef)) {
			if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE))
				sdata_info(sdata,
					   "HE AP VHT information is invalid, disable HE\n");
			ret = IEEE80211_STA_DISABLE_HE;
			goto out;
		}
260 261 262 263
	} else if (!ieee80211_chandef_vht_oper(&sdata->local->hw,
					       vht_cap_info,
					       vht_oper, ht_oper,
					       &vht_chandef)) {
264
		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
265
			sdata_info(sdata,
266
				   "AP VHT information is invalid, disable VHT\n");
267 268 269 270 271
		ret = IEEE80211_STA_DISABLE_VHT;
		goto out;
	}

	if (!cfg80211_chandef_valid(&vht_chandef)) {
272
		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
273 274
			sdata_info(sdata,
				   "AP VHT information is invalid, disable VHT\n");
275 276 277 278 279 280 281 282 283 284
		ret = IEEE80211_STA_DISABLE_VHT;
		goto out;
	}

	if (cfg80211_chandef_identical(chandef, &vht_chandef)) {
		ret = 0;
		goto out;
	}

	if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
285
		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
286 287
			sdata_info(sdata,
				   "AP VHT information doesn't match HT, disable VHT\n");
288 289 290 291 292 293 294 295 296
		ret = IEEE80211_STA_DISABLE_VHT;
		goto out;
	}

	*chandef = vht_chandef;

	ret = 0;

out:
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
	/*
	 * When tracking the current AP, don't do any further checks if the
	 * new chandef is identical to the one we're currently using for the
	 * connection. This keeps us from playing ping-pong with regulatory,
	 * without it the following can happen (for example):
	 *  - connect to an AP with 80 MHz, world regdom allows 80 MHz
	 *  - AP advertises regdom US
	 *  - CRDA loads regdom US with 80 MHz prohibited (old database)
	 *  - the code below detects an unsupported channel, downgrades, and
	 *    we disconnect from the AP in the caller
	 *  - disconnect causes CRDA to reload world regdomain and the game
	 *    starts anew.
	 * (see https://bugzilla.kernel.org/show_bug.cgi?id=70881)
	 *
	 * It seems possible that there are still scenarios with CSA or real
	 * bandwidth changes where a this could happen, but those cases are
	 * less common and wouldn't completely prevent using the AP.
	 */
	if (tracking &&
	    cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef))
		return ret;

319 320 321 322
	/* don't print the message below for VHT mismatch if VHT is disabled */
	if (ret & IEEE80211_STA_DISABLE_VHT)
		vht_chandef = *chandef;

323 324 325 326 327 328 329 330
	/*
	 * Ignore the DISABLED flag when we're already connected and only
	 * tracking the APs beacon for bandwidth changes - otherwise we
	 * might get disconnected here if we connect to an AP, update our
	 * regulatory information based on the AP's country IE and the
	 * information we have is wrong/outdated and disables the channel
	 * that we're actually using for the connection to the AP.
	 */
331
	while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
332 333
					tracking ? 0 :
						   IEEE80211_CHAN_DISABLED)) {
334 335
		if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
			ret = IEEE80211_STA_DISABLE_HT |
336 337
			      IEEE80211_STA_DISABLE_VHT |
			      IEEE80211_STA_DISABLE_HE;
338
			break;
339 340
		}

341
		ret |= ieee80211_chandef_downgrade(chandef);
342 343
	}

344 345
	if (!he_oper || !cfg80211_chandef_usable(sdata->wdev.wiphy, chandef,
						 IEEE80211_CHAN_NO_HE))
346 347
		ret |= IEEE80211_STA_DISABLE_HE;

348
	if (chandef->width != vht_chandef.width && !tracking)
349 350 351 352 353 354 355
		sdata_info(sdata,
			   "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");

	WARN_ON_ONCE(!cfg80211_chandef_valid(chandef));
	return ret;
}

356 357
static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
			       struct sta_info *sta,
358
			       const struct ieee80211_ht_cap *ht_cap,
359
			       const struct ieee80211_vht_cap *vht_cap,
360 361
			       const struct ieee80211_ht_operation *ht_oper,
			       const struct ieee80211_vht_operation *vht_oper,
L
Luca Coelho 已提交
362
			       const struct ieee80211_he_operation *he_oper,
363
			       const struct ieee80211_s1g_oper_ie *s1g_oper,
364
			       const u8 *bssid, u32 *changed)
365 366
{
	struct ieee80211_local *local = sdata->local;
367
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
L
Luca Coelho 已提交
368 369 370
	struct ieee80211_channel *chan = sdata->vif.bss_conf.chandef.chan;
	struct ieee80211_supported_band *sband =
		local->hw.wiphy->bands[chan->band];
371
	struct cfg80211_chan_def chandef;
372
	u16 ht_opmode;
373
	u32 flags;
374
	u32 vht_cap_info = 0;
375
	int ret;
376

377 378
	/* if HT was/is disabled, don't track any bandwidth changes */
	if (ifmgd->flags & IEEE80211_STA_DISABLE_HT || !ht_oper)
379 380
		return 0;

381 382 383 384
	/* don't check VHT if we associated as non-VHT station */
	if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
		vht_oper = NULL;

L
Luca Coelho 已提交
385 386
	/* don't check HE if we associated as non-HE station */
	if (ifmgd->flags & IEEE80211_STA_DISABLE_HE ||
387 388 389
	    !ieee80211_get_he_iftype_cap(sband,
					 ieee80211_vif_type_p2p(&sdata->vif)))

L
Luca Coelho 已提交
390 391
		he_oper = NULL;

392 393 394
	if (WARN_ON_ONCE(!sta))
		return -EINVAL;

395 396 397 398 399 400 401 402 403 404
	/*
	 * if bss configuration changed store the new one -
	 * this may be applicable even if channel is identical
	 */
	ht_opmode = le16_to_cpu(ht_oper->operation_mode);
	if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
		*changed |= BSS_CHANGED_HT;
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
	}

405 406 407
	if (vht_cap)
		vht_cap_info = le32_to_cpu(vht_cap->vht_cap_info);

L
Luca Coelho 已提交
408
	/* calculate new channel (type) based on HT/VHT/HE operation IEs */
409
	flags = ieee80211_determine_chantype(sdata, sband, chan, vht_cap_info,
L
Luca Coelho 已提交
410
					     ht_oper, vht_oper, he_oper,
411
					     s1g_oper, &chandef, true);
412 413 414 415 416 417 418 419 420 421

	/*
	 * Downgrade the new channel if we associated with restricted
	 * capabilities. For example, if we associated as a 20 MHz STA
	 * to a 40 MHz AP (due to regulatory, capabilities or config
	 * reasons) then switching to a 40 MHz channel now won't do us
	 * any good -- we couldn't use it with the AP.
	 */
	if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ &&
	    chandef.width == NL80211_CHAN_WIDTH_80P80)
422
		flags |= ieee80211_chandef_downgrade(&chandef);
423 424
	if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ &&
	    chandef.width == NL80211_CHAN_WIDTH_160)
425
		flags |= ieee80211_chandef_downgrade(&chandef);
426 427
	if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ &&
	    chandef.width > NL80211_CHAN_WIDTH_20)
428
		flags |= ieee80211_chandef_downgrade(&chandef);
429 430 431 432 433

	if (cfg80211_chandef_identical(&chandef, &sdata->vif.bss_conf.chandef))
		return 0;

	sdata_info(sdata,
434 435 436 437 438 439
		   "AP %pM changed bandwidth, new config is %d.%03d MHz, "
		   "width %d (%d.%03d/%d MHz)\n",
		   ifmgd->bssid, chandef.chan->center_freq,
		   chandef.chan->freq_offset, chandef.width,
		   chandef.center_freq1, chandef.freq1_offset,
		   chandef.center_freq2);
440 441 442

	if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
				      IEEE80211_STA_DISABLE_VHT |
443
				      IEEE80211_STA_DISABLE_HE |
444 445 446 447 448
				      IEEE80211_STA_DISABLE_40MHZ |
				      IEEE80211_STA_DISABLE_80P80MHZ |
				      IEEE80211_STA_DISABLE_160MHZ)) ||
	    !cfg80211_chandef_valid(&chandef)) {
		sdata_info(sdata,
449 450
			   "AP %pM changed caps/bw in a way we can't support (0x%x/0x%x) - disconnect\n",
			   ifmgd->bssid, flags, ifmgd->flags);
451 452 453 454
		return -EINVAL;
	}

	ret = ieee80211_vif_change_bandwidth(sdata, &chandef, changed);
455

456 457 458 459 460 461
	if (ret) {
		sdata_info(sdata,
			   "AP %pM changed bandwidth to incompatible one - disconnect\n",
			   ifmgd->bssid);
		return ret;
	}
462

463
	return 0;
464 465
}

J
Johannes Berg 已提交
466 467
/* frame sending functions */

J
Johannes Berg 已提交
468
static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
469
				struct sk_buff *skb, u8 ap_ht_param,
J
Johannes Berg 已提交
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
				struct ieee80211_supported_band *sband,
				struct ieee80211_channel *channel,
				enum ieee80211_smps_mode smps)
{
	u8 *pos;
	u32 flags = channel->flags;
	u16 cap;
	struct ieee80211_sta_ht_cap ht_cap;

	BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));

	memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
	ieee80211_apply_htcap_overrides(sdata, &ht_cap);

	/* determine capability flags */
	cap = ht_cap.cap;

487
	switch (ap_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
J
Johannes Berg 已提交
488 489 490 491 492 493 494 495 496 497 498 499 500 501
	case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
		if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
			cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
			cap &= ~IEEE80211_HT_CAP_SGI_40;
		}
		break;
	case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
		if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
			cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
			cap &= ~IEEE80211_HT_CAP_SGI_40;
		}
		break;
	}

502 503 504 505 506 507 508 509 510 511
	/*
	 * If 40 MHz was disabled associate as though we weren't
	 * capable of 40 MHz -- some broken APs will never fall
	 * back to trying to transmit in 20 MHz.
	 */
	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_40MHZ) {
		cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
		cap &= ~IEEE80211_HT_CAP_SGI_40;
	}

J
Johannes Berg 已提交
512 513 514 515 516 517
	/* set SM PS mode properly */
	cap &= ~IEEE80211_HT_CAP_SM_PS;
	switch (smps) {
	case IEEE80211_SMPS_AUTOMATIC:
	case IEEE80211_SMPS_NUM_MODES:
		WARN_ON(1);
518
		fallthrough;
J
Johannes Berg 已提交
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
	case IEEE80211_SMPS_OFF:
		cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
			IEEE80211_HT_CAP_SM_PS_SHIFT;
		break;
	case IEEE80211_SMPS_STATIC:
		cap |= WLAN_HT_CAP_SM_PS_STATIC <<
			IEEE80211_HT_CAP_SM_PS_SHIFT;
		break;
	case IEEE80211_SMPS_DYNAMIC:
		cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
			IEEE80211_HT_CAP_SM_PS_SHIFT;
		break;
	}

	/* reserve and fill IE */
	pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
	ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
}

538 539 540 541
/* This function determines vht capability flags for the association
 * and builds the IE.
 * Note - the function may set the owner of the MU-MIMO capability
 */
542 543
static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
				 struct sk_buff *skb,
544 545
				 struct ieee80211_supported_band *sband,
				 struct ieee80211_vht_cap *ap_vht_cap)
546
{
547
	struct ieee80211_local *local = sdata->local;
548 549 550
	u8 *pos;
	u32 cap;
	struct ieee80211_sta_vht_cap vht_cap;
551
	u32 mask, ap_bf_sts, our_bf_sts;
552 553 554 555

	BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));

	memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
556
	ieee80211_apply_vhtcap_overrides(sdata, &vht_cap);
557 558 559 560

	/* determine capability flags */
	cap = vht_cap.cap;

J
Johannes Berg 已提交
561
	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) {
562 563 564 565 566 567
		u32 bw = cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;

		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
		if (bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
		    bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
			cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
J
Johannes Berg 已提交
568 569 570 571
	}

	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) {
		cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
572
		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
J
Johannes Berg 已提交
573 574
	}

575 576 577 578 579 580
	/*
	 * Some APs apparently get confused if our capabilities are better
	 * than theirs, so restrict what we advertise in the assoc request.
	 */
	if (!(ap_vht_cap->vht_cap_info &
			cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)))
581 582 583 584 585 586 587
		cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
			 IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
	else if (!(ap_vht_cap->vht_cap_info &
			cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
		cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;

	/*
588
	 * If some other vif is using the MU-MIMO capability we cannot associate
589 590 591 592 593 594 595 596 597 598
	 * using MU-MIMO - this will lead to contradictions in the group-id
	 * mechanism.
	 * Ownership is defined since association request, in order to avoid
	 * simultaneous associations with MU-MIMO.
	 */
	if (cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) {
		bool disable_mu_mimo = false;
		struct ieee80211_sub_if_data *other;

		list_for_each_entry_rcu(other, &local->interfaces, list) {
599
			if (other->vif.mu_mimo_owner) {
600 601 602 603 604 605 606
				disable_mu_mimo = true;
				break;
			}
		}
		if (disable_mu_mimo)
			cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
		else
607
			sdata->vif.mu_mimo_owner = true;
608
	}
609

610 611 612 613 614 615 616 617 618 619
	mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;

	ap_bf_sts = le32_to_cpu(ap_vht_cap->vht_cap_info) & mask;
	our_bf_sts = cap & mask;

	if (ap_bf_sts < our_bf_sts) {
		cap &= ~mask;
		cap |= ap_bf_sts;
	}

620
	/* reserve and fill IE */
M
Mahesh Palivela 已提交
621
	pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
622 623 624
	ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
}

L
Luca Coelho 已提交
625 626 627 628 629 630 631 632 633
/* This function determines HE capability flags for the association
 * and builds the IE.
 */
static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
				struct sk_buff *skb,
				struct ieee80211_supported_band *sband)
{
	u8 *pos;
	const struct ieee80211_sta_he_cap *he_cap = NULL;
634
	struct ieee80211_chanctx_conf *chanctx_conf;
L
Luca Coelho 已提交
635
	u8 he_cap_size;
636 637 638 639 640 641 642 643 644 645
	bool reg_cap = false;

	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
	if (!WARN_ON_ONCE(!chanctx_conf))
		reg_cap = cfg80211_chandef_usable(sdata->wdev.wiphy,
						  &chanctx_conf->def,
						  IEEE80211_CHAN_NO_HE);

	rcu_read_unlock();
L
Luca Coelho 已提交
646

647 648
	he_cap = ieee80211_get_he_iftype_cap(sband,
					     ieee80211_vif_type_p2p(&sdata->vif));
649
	if (!he_cap || !reg_cap)
L
Luca Coelho 已提交
650 651 652 653 654 655 656 657 658 659 660 661 662
		return;

	/*
	 * TODO: the 1 added is because this temporarily is under the EXTENSION
	 * IE. Get rid of it when it moves.
	 */
	he_cap_size =
		2 + 1 + sizeof(he_cap->he_cap_elem) +
		ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem) +
		ieee80211_he_ppe_size(he_cap->ppe_thres[0],
				      he_cap->he_cap_elem.phy_cap_info);
	pos = skb_put(skb, he_cap_size);
	ieee80211_ie_build_he_cap(pos, he_cap, pos + he_cap_size);
663 664

	ieee80211_ie_build_he_6ghz_cap(sdata, skb);
L
Luca Coelho 已提交
665 666
}

J
Johannes Berg 已提交
667 668 669 670 671 672 673
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
674
	u8 *pos, qos_info, *ie_start;
J
Johannes Berg 已提交
675
	size_t offset = 0, noffset;
676
	int i, count, rates_len, supp_rates_len, shift;
J
Johannes Berg 已提交
677 678
	u16 capab;
	struct ieee80211_supported_band *sband;
J
Johannes Berg 已提交
679 680
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_channel *chan;
681
	u32 rates = 0;
682
	__le16 listen_int;
683
	struct element *ext_capa = NULL;
684 685
	enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif);
	const struct ieee80211_sband_iftype_data *iftd;
686
	struct ieee80211_prep_tx_info info = {};
687 688 689 690 691 692

	/* we know it's writable, cast away the const */
	if (assoc_data->ie_len)
		ext_capa = (void *)cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
						      assoc_data->ie,
						      assoc_data->ie_len);
J
Johannes Berg 已提交
693

694
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
695

J
Johannes Berg 已提交
696 697 698 699 700 701
	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
	if (WARN_ON(!chanctx_conf)) {
		rcu_read_unlock();
		return;
	}
702
	chan = chanctx_conf->def.chan;
J
Johannes Berg 已提交
703 704
	rcu_read_unlock();
	sband = local->hw.wiphy->bands[chan->band];
705
	shift = ieee80211_vif_get_shift(&sdata->vif);
J
Johannes Berg 已提交
706 707 708 709 710 711 712 713

	if (assoc_data->supp_rates_len) {
		/*
		 * Get all rates supported by the device and the AP as
		 * some APs don't like getting a superset of their rates
		 * in the association request (e.g. D-Link DAP 1353 in
		 * b-only mode)...
		 */
714 715 716 717
		rates_len = ieee80211_parse_bitrates(&chanctx_conf->def, sband,
						     assoc_data->supp_rates,
						     assoc_data->supp_rates_len,
						     &rates);
J
Johannes Berg 已提交
718 719 720 721 722 723
	} else {
		/*
		 * In case AP not provide any supported rates information
		 * before association, we send information element(s) with
		 * all rates that we support.
		 */
724 725 726 727 728
		rates_len = 0;
		for (i = 0; i < sband->n_bitrates; i++) {
			rates |= BIT(i);
			rates_len++;
		}
J
Johannes Berg 已提交
729 730
	}

731 732
	iftd = ieee80211_get_sband_iftype_data(sband, iftype);

J
Johannes Berg 已提交
733 734 735 736 737 738 739
	skb = alloc_skb(local->hw.extra_tx_headroom +
			sizeof(*mgmt) + /* bit too much but doesn't matter */
			2 + assoc_data->ssid_len + /* SSID */
			4 + rates_len + /* (extended) rates */
			4 + /* power capability */
			2 + 2 * sband->n_channels + /* supported channels */
			2 + sizeof(struct ieee80211_ht_cap) + /* HT */
M
Mahesh Palivela 已提交
740
			2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
L
Luca Coelho 已提交
741 742 743
			2 + 1 + sizeof(struct ieee80211_he_cap_elem) + /* HE */
				sizeof(struct ieee80211_he_mcs_nss_supp) +
				IEEE80211_HE_PPE_THRES_MAX_LEN +
744
			2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
J
Johannes Berg 已提交
745
			assoc_data->ie_len + /* extra IEs */
746
			(assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) +
747 748
			9 + /* WMM */
			(iftd ? iftd->vendor_elems.len : 0),
J
Johannes Berg 已提交
749 750 751 752 753 754 755 756
			GFP_KERNEL);
	if (!skb)
		return;

	skb_reserve(skb, local->hw.extra_tx_headroom);

	capab = WLAN_CAPABILITY_ESS;

757
	if (sband->band == NL80211_BAND_2GHZ) {
758 759
		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
		capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
J
Johannes Berg 已提交
760 761 762 763 764 765
	}

	if (assoc_data->capability & WLAN_CAPABILITY_PRIVACY)
		capab |= WLAN_CAPABILITY_PRIVACY;

	if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
766
	    ieee80211_hw_check(&local->hw, SPECTRUM_MGMT))
J
Johannes Berg 已提交
767 768
		capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;

769 770 771
	if (ifmgd->flags & IEEE80211_STA_ENABLE_RRM)
		capab |= WLAN_CAPABILITY_RADIO_MEASURE;

772
	mgmt = skb_put_zero(skb, 24);
J
Johannes Berg 已提交
773 774 775 776
	memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN);
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
	memcpy(mgmt->bssid, assoc_data->bss->bssid, ETH_ALEN);

777 778 779
	listen_int = cpu_to_le16(sband->band == NL80211_BAND_S1GHZ ?
			ieee80211_encode_usf(local->hw.conf.listen_interval) :
			local->hw.conf.listen_interval);
J
Johannes Berg 已提交
780 781 782 783 784
	if (!is_zero_ether_addr(assoc_data->prev_bssid)) {
		skb_put(skb, 10);
		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						  IEEE80211_STYPE_REASSOC_REQ);
		mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
785
		mgmt->u.reassoc_req.listen_interval = listen_int;
J
Johannes Berg 已提交
786 787
		memcpy(mgmt->u.reassoc_req.current_ap, assoc_data->prev_bssid,
		       ETH_ALEN);
788
		info.subtype = IEEE80211_STYPE_REASSOC_REQ;
J
Johannes Berg 已提交
789 790 791 792 793
	} else {
		skb_put(skb, 4);
		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						  IEEE80211_STYPE_ASSOC_REQ);
		mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
794
		mgmt->u.assoc_req.listen_interval = listen_int;
795
		info.subtype = IEEE80211_STYPE_ASSOC_REQ;
J
Johannes Berg 已提交
796 797 798 799
	}

	/* SSID */
	pos = skb_put(skb, 2 + assoc_data->ssid_len);
800
	ie_start = pos;
J
Johannes Berg 已提交
801 802 803 804
	*pos++ = WLAN_EID_SSID;
	*pos++ = assoc_data->ssid_len;
	memcpy(pos, assoc_data->ssid, assoc_data->ssid_len);

805 806 807
	if (sband->band == NL80211_BAND_S1GHZ)
		goto skip_rates;

J
Johannes Berg 已提交
808 809 810 811 812 813 814 815 816 817 818 819
	/* add all rates which were marked to be used above */
	supp_rates_len = rates_len;
	if (supp_rates_len > 8)
		supp_rates_len = 8;

	pos = skb_put(skb, supp_rates_len + 2);
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos++ = supp_rates_len;

	count = 0;
	for (i = 0; i < sband->n_bitrates; i++) {
		if (BIT(i) & rates) {
820 821 822
			int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
						5 * (1 << shift));
			*pos++ = (u8) rate;
J
Johannes Berg 已提交
823 824 825 826 827 828 829 830 831 832 833 834
			if (++count == 8)
				break;
		}
	}

	if (rates_len > count) {
		pos = skb_put(skb, rates_len - count + 2);
		*pos++ = WLAN_EID_EXT_SUPP_RATES;
		*pos++ = rates_len - count;

		for (i++; i < sband->n_bitrates; i++) {
			if (BIT(i) & rates) {
835 836 837 838
				int rate;
				rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
						    5 * (1 << shift));
				*pos++ = (u8) rate;
J
Johannes Berg 已提交
839 840 841 842
			}
		}
	}

843
skip_rates:
844 845
	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT ||
	    capab & WLAN_CAPABILITY_RADIO_MEASURE) {
J
Johannes Berg 已提交
846 847 848 849
		pos = skb_put(skb, 4);
		*pos++ = WLAN_EID_PWR_CAPABILITY;
		*pos++ = 2;
		*pos++ = 0; /* min tx power */
850 851
		 /* max tx power */
		*pos++ = ieee80211_chandef_max_power(&chanctx_conf->def);
852
	}
J
Johannes Berg 已提交
853

854 855 856 857 858 859 860 861 862
	/*
	 * Per spec, we shouldn't include the list of channels if we advertise
	 * support for extended channel switching, but we've always done that;
	 * (for now?) apply this restriction only on the (new) 6 GHz band.
	 */
	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT &&
	    (sband->band != NL80211_BAND_6GHZ ||
	     !ext_capa || ext_capa->datalen < 1 ||
	     !(ext_capa->data[0] & WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING))) {
J
Johannes Berg 已提交
863 864 865 866 867 868 869 870 871 872 873
		/* TODO: get this in reg domain format */
		pos = skb_put(skb, 2 * sband->n_channels + 2);
		*pos++ = WLAN_EID_SUPPORTED_CHANNELS;
		*pos++ = 2 * sband->n_channels;
		for (i = 0; i < sband->n_channels; i++) {
			*pos++ = ieee80211_frequency_to_channel(
					sband->channels[i].center_freq);
			*pos++ = 1; /* one channel in the subband*/
		}
	}

874 875
	/* Set MBSSID support for HE AP if needed */
	if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) &&
876 877 878
	    !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len &&
	    ext_capa && ext_capa->datalen >= 3)
		ext_capa->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
879

J
Johannes Berg 已提交
880
	/* if present, add any custom IEs that go before HT */
881
	if (assoc_data->ie_len) {
J
Johannes Berg 已提交
882 883 884 885 886 887 888 889 890 891
		static const u8 before_ht[] = {
			WLAN_EID_SSID,
			WLAN_EID_SUPP_RATES,
			WLAN_EID_EXT_SUPP_RATES,
			WLAN_EID_PWR_CAPABILITY,
			WLAN_EID_SUPPORTED_CHANNELS,
			WLAN_EID_RSN,
			WLAN_EID_QOS_CAPA,
			WLAN_EID_RRM_ENABLED_CAPABILITIES,
			WLAN_EID_MOBILITY_DOMAIN,
892 893
			WLAN_EID_FAST_BSS_TRANSITION,	/* reassoc only */
			WLAN_EID_RIC_DATA,		/* reassoc only */
J
Johannes Berg 已提交
894 895
			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
		};
896 897 898 899
		static const u8 after_ric[] = {
			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
			WLAN_EID_HT_CAPABILITY,
			WLAN_EID_BSS_COEX_2040,
900
			/* luckily this is almost always there */
901 902 903 904
			WLAN_EID_EXT_CAPABILITY,
			WLAN_EID_QOS_TRAFFIC_CAPA,
			WLAN_EID_TIM_BCAST_REQ,
			WLAN_EID_INTERWORKING,
905
			/* 60 GHz (Multi-band, DMG, MMS) can't happen */
906 907 908 909 910 911 912 913 914 915 916
			WLAN_EID_VHT_CAPABILITY,
			WLAN_EID_OPMODE_NOTIF,
		};

		noffset = ieee80211_ie_split_ric(assoc_data->ie,
						 assoc_data->ie_len,
						 before_ht,
						 ARRAY_SIZE(before_ht),
						 after_ric,
						 ARRAY_SIZE(after_ric),
						 offset);
917
		skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
J
Johannes Berg 已提交
918 919 920
		offset = noffset;
	}

J
Johannes Berg 已提交
921 922 923 924
	if (WARN_ON_ONCE((ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
			 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)))
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;

925 926
	if (sband->band != NL80211_BAND_6GHZ &&
	    !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
927
		ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
928
				    sband, chan, sdata->smps_mode);
J
Johannes Berg 已提交
929

930 931 932
	/* if present, add any custom IEs that go before VHT */
	if (assoc_data->ie_len) {
		static const u8 before_vht[] = {
933 934 935 936
			/*
			 * no need to list the ones split off before HT
			 * or generated here
			 */
937 938 939 940 941
			WLAN_EID_BSS_COEX_2040,
			WLAN_EID_EXT_CAPABILITY,
			WLAN_EID_QOS_TRAFFIC_CAPA,
			WLAN_EID_TIM_BCAST_REQ,
			WLAN_EID_INTERWORKING,
942
			/* 60 GHz (Multi-band, DMG, MMS) can't happen */
943
		};
944 945

		/* RIC already taken above, so no need to handle here anymore */
946 947 948
		noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
					     before_vht, ARRAY_SIZE(before_vht),
					     offset);
949
		skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
950 951 952
		offset = noffset;
	}

L
Luca Coelho 已提交
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
	/* if present, add any custom IEs that go before HE */
	if (assoc_data->ie_len) {
		static const u8 before_he[] = {
			/*
			 * no need to list the ones split off before VHT
			 * or generated here
			 */
			WLAN_EID_OPMODE_NOTIF,
			WLAN_EID_EXTENSION, WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE,
			/* 11ai elements */
			WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_SESSION,
			WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_PUBLIC_KEY,
			WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_KEY_CONFIRM,
			WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_HLP_CONTAINER,
			WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN,
			/* TODO: add 11ah/11aj/11ak elements */
		};

		/* RIC already taken above, so no need to handle here anymore */
		noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
					     before_he, ARRAY_SIZE(before_he),
					     offset);
		pos = skb_put(skb, noffset - offset);
		memcpy(pos, assoc_data->ie + offset, noffset - offset);
		offset = noffset;
	}

980 981
	if (sband->band != NL80211_BAND_6GHZ &&
	    !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
982 983
		ieee80211_add_vht_ie(sdata, skb, sband,
				     &assoc_data->ap_vht_cap);
984

985 986 987 988 989 990 991 992 993
	/*
	 * If AP doesn't support HT, mark HE as disabled.
	 * If on the 5GHz band, make sure it supports VHT.
	 */
	if (ifmgd->flags & IEEE80211_STA_DISABLE_HT ||
	    (sband->band == NL80211_BAND_5GHZ &&
	     ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
		ifmgd->flags |= IEEE80211_STA_DISABLE_HE;

L
Luca Coelho 已提交
994 995 996 997
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE))
		ieee80211_add_he_ie(sdata, skb, sband);

	/* if present, add any custom non-vendor IEs that go after HE */
998
	if (assoc_data->ie_len) {
J
Johannes Berg 已提交
999 1000 1001
		noffset = ieee80211_ie_split_vendor(assoc_data->ie,
						    assoc_data->ie_len,
						    offset);
1002
		skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
J
Johannes Berg 已提交
1003 1004 1005
		offset = noffset;
	}

1006 1007
	if (assoc_data->wmm) {
		if (assoc_data->uapsd) {
1008 1009
			qos_info = ifmgd->uapsd_queues;
			qos_info |= (ifmgd->uapsd_max_sp_len <<
J
Johannes Berg 已提交
1010 1011 1012 1013 1014
				     IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
		} else {
			qos_info = 0;
		}

1015
		pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info);
J
Johannes Berg 已提交
1016 1017
	}

1018 1019
	if (sband->band == NL80211_BAND_S1GHZ) {
		ieee80211_add_aid_request_ie(sdata, skb);
1020
		ieee80211_add_s1g_capab_ie(sdata, &sband->s1g_cap, skb);
1021
	}
1022

1023 1024 1025
	if (iftd && iftd->vendor_elems.data && iftd->vendor_elems.len)
		skb_put_data(skb, iftd->vendor_elems.data, iftd->vendor_elems.len);

J
Johannes Berg 已提交
1026
	/* add any remaining custom (i.e. vendor specific here) IEs */
1027
	if (assoc_data->ie_len) {
J
Johannes Berg 已提交
1028
		noffset = assoc_data->ie_len;
1029
		skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
J
Johannes Berg 已提交
1030 1031
	}

1032 1033 1034 1035 1036 1037
	if (assoc_data->fils_kek_len &&
	    fils_encrypt_assoc_req(skb, assoc_data) < 0) {
		dev_kfree_skb(skb);
		return;
	}

1038 1039 1040 1041 1042
	pos = skb_tail_pointer(skb);
	kfree(ifmgd->assoc_req_ies);
	ifmgd->assoc_req_ies = kmemdup(ie_start, pos - ie_start, GFP_ATOMIC);
	ifmgd->assoc_req_ies_len = pos - ie_start;

1043
	drv_mgd_prepare_tx(local, sdata, &info);
J
Johannes Berg 已提交
1044

J
Johannes Berg 已提交
1045
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
1046
	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
1047 1048
		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
						IEEE80211_TX_INTFL_MLME_CONN_TX;
J
Johannes Berg 已提交
1049 1050 1051
	ieee80211_tx_skb(sdata, skb);
}

1052 1053 1054 1055 1056 1057
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_pspoll *pspoll;
	struct sk_buff *skb;

1058 1059
	skb = ieee80211_pspoll_get(&local->hw, &sdata->vif);
	if (!skb)
1060 1061
		return;

1062 1063
	pspoll = (struct ieee80211_pspoll *) skb->data;
	pspoll->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
1064

1065 1066
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
	ieee80211_tx_skb(sdata, skb);
1067 1068
}

1069 1070
void ieee80211_send_nullfunc(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
1071
			     bool powersave)
1072 1073
{
	struct sk_buff *skb;
1074
	struct ieee80211_hdr_3addr *nullfunc;
1075
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1076

1077 1078
	skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif,
		!ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP));
1079
	if (!skb)
1080 1081
		return;

1082
	nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
1083
	if (powersave)
1084
		nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
1085

1086 1087
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
					IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
1088

1089
	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
1090 1091
		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;

1092
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
1093 1094
		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE;

1095
	ieee80211_tx_skb(sdata, skb);
1096 1097
}

1098 1099
void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
				   struct ieee80211_sub_if_data *sdata)
1100 1101 1102 1103 1104 1105 1106 1107 1108
{
	struct sk_buff *skb;
	struct ieee80211_hdr *nullfunc;
	__le16 fc;

	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
		return;

	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30);
1109
	if (!skb)
1110
		return;
1111

1112 1113
	skb_reserve(skb, local->hw.extra_tx_headroom);

1114
	nullfunc = skb_put_zero(skb, 30);
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
			 IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
	nullfunc->frame_control = fc;
	memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
	memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);
	memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN);

	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
	ieee80211_tx_skb(sdata, skb);
}

1127 1128 1129 1130 1131
/* spectrum management related things */
static void ieee80211_chswitch_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
1132
	struct ieee80211_local *local = sdata->local;
1133
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1134
	int ret;
1135

1136
	if (!ieee80211_sdata_running(sdata))
1137 1138
		return;

1139
	sdata_lock(sdata);
1140 1141 1142
	mutex_lock(&local->mtx);
	mutex_lock(&local->chanctx_mtx);

1143 1144
	if (!ifmgd->associated)
		goto out;
1145

1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
	if (!sdata->vif.csa_active)
		goto out;

	/*
	 * using reservation isn't immediate as it may be deferred until later
	 * with multi-vif. once reservation is complete it will re-schedule the
	 * work with no reserved_chanctx so verify chandef to check if it
	 * completed successfully
	 */

	if (sdata->reserved_chanctx) {
		/*
		 * with multi-vif csa driver may call ieee80211_csa_finish()
		 * many times while waiting for other interfaces to use their
		 * reservations
		 */
		if (sdata->reserved_ready)
			goto out;

		ret = ieee80211_vif_use_reserved_context(sdata);
		if (ret) {
			sdata_info(sdata,
				   "failed to use reserved channel context, disconnecting (err=%d)\n",
				   ret);
			ieee80211_queue_work(&sdata->local->hw,
					     &ifmgd->csa_connection_drop_work);
			goto out;
		}

		goto out;
	}

	if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
					&sdata->csa_chandef)) {
1180
		sdata_info(sdata,
1181
			   "failed to finalize channel switch, disconnecting\n");
1182 1183 1184 1185
		ieee80211_queue_work(&sdata->local->hw,
				     &ifmgd->csa_connection_drop_work);
		goto out;
	}
1186

1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
	ifmgd->csa_waiting_bcn = true;

	ieee80211_sta_reset_beacon_monitor(sdata);
	ieee80211_sta_reset_conn_monitor(sdata);

out:
	mutex_unlock(&local->chanctx_mtx);
	mutex_unlock(&local->mtx);
	sdata_unlock(sdata);
}

static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	int ret;

	sdata_assert_lock(sdata);

	WARN_ON(!sdata->vif.csa_active);
1207

1208 1209 1210 1211 1212
	if (sdata->csa_block_tx) {
		ieee80211_wake_vif_queues(local, sdata,
					  IEEE80211_QUEUE_STOP_REASON_CSA);
		sdata->csa_block_tx = false;
	}
1213

1214 1215
	sdata->vif.csa_active = false;
	ifmgd->csa_waiting_bcn = false;
1216 1217 1218 1219 1220
	/*
	 * If the CSA IE is still present on the beacon after the switch,
	 * we need to consider it as a new CSA (possibly to self).
	 */
	ifmgd->beacon_crc_valid = false;
1221

1222 1223 1224 1225 1226 1227
	ret = drv_post_channel_switch(sdata);
	if (ret) {
		sdata_info(sdata,
			   "driver post channel switch failed, disconnecting\n");
		ieee80211_queue_work(&local->hw,
				     &ifmgd->csa_connection_drop_work);
1228
		return;
1229
	}
1230 1231

	cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
1232 1233
}

1234 1235
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
{
J
Johannes Berg 已提交
1236 1237
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1238 1239 1240

	trace_api_chswitch_done(sdata, success);
	if (!success) {
1241 1242 1243 1244 1245 1246
		sdata_info(sdata,
			   "driver channel switch failed, disconnecting\n");
		ieee80211_queue_work(&sdata->local->hw,
				     &ifmgd->csa_connection_drop_work);
	} else {
		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
1247 1248 1249 1250
	}
}
EXPORT_SYMBOL(ieee80211_chswitch_done);

1251
static void ieee80211_chswitch_timer(struct timer_list *t)
1252 1253
{
	struct ieee80211_sub_if_data *sdata =
1254
		from_timer(sdata, t, u.mgd.chswitch_timer);
1255

1256
	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
1257 1258
}

1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
static void
ieee80211_sta_abort_chanswitch(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;

	if (!local->ops->abort_channel_switch)
		return;

	mutex_lock(&local->mtx);

	mutex_lock(&local->chanctx_mtx);
	ieee80211_vif_unreserve_chanctx(sdata);
	mutex_unlock(&local->chanctx_mtx);

	if (sdata->csa_block_tx)
		ieee80211_wake_vif_queues(local, sdata,
					  IEEE80211_QUEUE_STOP_REASON_CSA);

	sdata->csa_block_tx = false;
	sdata->vif.csa_active = false;

	mutex_unlock(&local->mtx);

	drv_abort_channel_switch(sdata);
}

1285
static void
J
Johannes Berg 已提交
1286
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1287 1288
				 u64 timestamp, u32 device_timestamp,
				 struct ieee802_11_elems *elems,
1289
				 bool beacon)
1290
{
1291
	struct ieee80211_local *local = sdata->local;
1292
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1293
	struct cfg80211_bss *cbss = ifmgd->associated;
1294
	struct ieee80211_chanctx_conf *conf;
J
Johannes Berg 已提交
1295
	struct ieee80211_chanctx *chanctx;
1296
	enum nl80211_band current_band;
1297
	struct ieee80211_csa_ie csa_ie;
1298
	struct ieee80211_channel_switch ch_switch;
1299
	struct ieee80211_bss *bss;
1300
	int res;
1301

1302
	sdata_assert_lock(sdata);
1303

1304
	if (!cbss)
1305 1306
		return;

1307
	if (local->scanning)
1308 1309
		return;

1310
	current_band = cbss->channel->band;
1311
	bss = (void *)cbss->priv;
1312
	res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
1313
					   bss->vht_cap_info,
1314
					   ifmgd->flags,
1315
					   ifmgd->associated->bssid, &csa_ie);
1316 1317 1318 1319

	if (!res) {
		ch_switch.timestamp = timestamp;
		ch_switch.device_timestamp = device_timestamp;
1320
		ch_switch.block_tx = csa_ie.mode;
1321 1322 1323 1324 1325
		ch_switch.chandef = csa_ie.chandef;
		ch_switch.count = csa_ie.count;
		ch_switch.delay = csa_ie.max_switch_time;
	}

1326 1327
	if (res < 0)
		goto lock_and_drop_connection;
1328

1329 1330 1331 1332 1333
	if (beacon && sdata->vif.csa_active && !ifmgd->csa_waiting_bcn) {
		if (res)
			ieee80211_sta_abort_chanswitch(sdata);
		else
			drv_channel_switch_rx_beacon(sdata, &ch_switch);
1334 1335 1336 1337 1338
		return;
	} else if (sdata->vif.csa_active || res) {
		/* disregard subsequent announcements if already processing */
		return;
	}
1339

1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
	if (sdata->vif.bss_conf.chandef.chan->band !=
	    csa_ie.chandef.chan->band) {
		sdata_info(sdata,
			   "AP %pM switches to different band (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
			   ifmgd->associated->bssid,
			   csa_ie.chandef.chan->center_freq,
			   csa_ie.chandef.width, csa_ie.chandef.center_freq1,
			   csa_ie.chandef.center_freq2);
		goto lock_and_drop_connection;
	}

1351
	if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
1352 1353
				     IEEE80211_CHAN_DISABLED)) {
		sdata_info(sdata,
1354 1355 1356
			   "AP %pM switches to unsupported channel "
			   "(%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), "
			   "disconnecting\n",
1357
			   ifmgd->associated->bssid,
1358
			   csa_ie.chandef.chan->center_freq,
1359
			   csa_ie.chandef.chan->freq_offset,
1360
			   csa_ie.chandef.width, csa_ie.chandef.center_freq1,
1361
			   csa_ie.chandef.freq1_offset,
1362
			   csa_ie.chandef.center_freq2);
1363
		goto lock_and_drop_connection;
1364 1365
	}

1366
	if (cfg80211_chandef_identical(&csa_ie.chandef,
1367 1368
				       &sdata->vif.bss_conf.chandef) &&
	    (!csa_ie.mode || !beacon)) {
1369 1370 1371 1372 1373 1374 1375 1376 1377
		if (ifmgd->csa_ignored_same_chan)
			return;
		sdata_info(sdata,
			   "AP %pM tries to chanswitch to same channel, ignore\n",
			   ifmgd->associated->bssid);
		ifmgd->csa_ignored_same_chan = true;
		return;
	}

1378 1379 1380 1381 1382 1383 1384 1385
	/*
	 * Drop all TDLS peers - either we disconnect or move to a different
	 * channel from this point on. There's no telling what our peer will do.
	 * The TDLS WIDER_BW scenario is also problematic, as peers might now
	 * have an incompatible wider chandef.
	 */
	ieee80211_teardown_tdls_peers(sdata);

1386
	mutex_lock(&local->mtx);
1387
	mutex_lock(&local->chanctx_mtx);
1388 1389 1390 1391 1392
	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
					 lockdep_is_held(&local->chanctx_mtx));
	if (!conf) {
		sdata_info(sdata,
			   "no channel context assigned to vif?, disconnecting\n");
1393
		goto drop_connection;
1394 1395 1396 1397
	}

	chanctx = container_of(conf, struct ieee80211_chanctx, conf);

1398
	if (local->use_chanctx &&
1399
	    !ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA)) {
1400 1401
		sdata_info(sdata,
			   "driver doesn't support chan-switch with channel contexts\n");
1402
		goto drop_connection;
J
Johannes Berg 已提交
1403 1404
	}

1405 1406 1407
	if (drv_pre_channel_switch(sdata, &ch_switch)) {
		sdata_info(sdata,
			   "preparing for channel switch failed, disconnecting\n");
1408
		goto drop_connection;
1409 1410
	}

1411 1412 1413
	res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef,
					    chanctx->mode, false);
	if (res) {
J
Johannes Berg 已提交
1414
		sdata_info(sdata,
1415 1416
			   "failed to reserve channel context for channel switch, disconnecting (err=%d)\n",
			   res);
1417
		goto drop_connection;
J
Johannes Berg 已提交
1418
	}
1419
	mutex_unlock(&local->chanctx_mtx);
J
Johannes Berg 已提交
1420

1421
	sdata->vif.csa_active = true;
1422
	sdata->csa_chandef = csa_ie.chandef;
1423
	sdata->csa_block_tx = csa_ie.mode;
1424
	ifmgd->csa_ignored_same_chan = false;
1425
	ifmgd->beacon_crc_valid = false;
J
Johannes Berg 已提交
1426

1427
	if (sdata->csa_block_tx)
1428 1429
		ieee80211_stop_vif_queues(local, sdata,
					  IEEE80211_QUEUE_STOP_REASON_CSA);
1430
	mutex_unlock(&local->mtx);
1431

1432
	cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
1433
					  csa_ie.count, csa_ie.mode);
1434

1435
	if (local->ops->channel_switch) {
1436
		/* use driver's channel switch callback */
1437
		drv_channel_switch(local, sdata, &ch_switch);
1438 1439 1440 1441
		return;
	}

	/* channel switch handled in software */
1442
	if (csa_ie.count <= 1)
1443
		ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
1444
	else
1445
		mod_timer(&ifmgd->chswitch_timer,
1446 1447
			  TU_TO_EXP_TIME((csa_ie.count - 1) *
					 cbss->beacon_interval));
1448
	return;
1449 1450 1451
 lock_and_drop_connection:
	mutex_lock(&local->mtx);
	mutex_lock(&local->chanctx_mtx);
1452
 drop_connection:
1453 1454 1455 1456 1457 1458 1459 1460
	/*
	 * This is just so that the disconnect flow will know that
	 * we were trying to switch channel and failed. In case the
	 * mode is 1 (we are not allowed to Tx), we will know not to
	 * send a deauthentication frame. Those two fields will be
	 * reset when the disconnection worker runs.
	 */
	sdata->vif.csa_active = true;
1461
	sdata->csa_block_tx = csa_ie.mode;
1462

1463 1464 1465
	ieee80211_queue_work(&local->hw, &ifmgd->csa_connection_drop_work);
	mutex_unlock(&local->chanctx_mtx);
	mutex_unlock(&local->mtx);
1466 1467
}

1468 1469 1470 1471 1472 1473
static bool
ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
				 struct ieee80211_channel *channel,
				 const u8 *country_ie, u8 country_ie_len,
				 const u8 *pwr_constr_elem,
				 int *chan_pwr, int *pwr_reduction)
1474
{
1475 1476
	struct ieee80211_country_ie_triplet *triplet;
	int chan = ieee80211_frequency_to_channel(channel->center_freq);
1477
	int i, chan_increment;
1478
	bool have_chan_pwr = false;
1479

1480 1481
	/* Invalid IE */
	if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
1482
		return false;
1483

1484 1485 1486 1487 1488 1489
	triplet = (void *)(country_ie + 3);
	country_ie_len -= 3;

	switch (channel->band) {
	default:
		WARN_ON_ONCE(1);
1490
		fallthrough;
1491 1492
	case NL80211_BAND_2GHZ:
	case NL80211_BAND_60GHZ:
1493 1494
		chan_increment = 1;
		break;
1495
	case NL80211_BAND_5GHZ:
1496 1497
		chan_increment = 4;
		break;
1498 1499 1500 1501 1502 1503 1504 1505 1506
	case NL80211_BAND_6GHZ:
		/*
		 * In the 6 GHz band, the "maximum transmit power level"
		 * field in the triplets is reserved, and thus will be
		 * zero and we shouldn't use it to control TX power.
		 * The actual TX power will be given in the transmit
		 * power envelope element instead.
		 */
		return false;
1507
	}
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518

	/* find channel */
	while (country_ie_len >= 3) {
		u8 first_channel = triplet->chans.first_channel;

		if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID)
			goto next;

		for (i = 0; i < triplet->chans.num_channels; i++) {
			if (first_channel + i * chan_increment == chan) {
				have_chan_pwr = true;
1519
				*chan_pwr = triplet->chans.max_power;
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
				break;
			}
		}
		if (have_chan_pwr)
			break;

 next:
		triplet++;
		country_ie_len -= 3;
	}

1531
	if (have_chan_pwr && pwr_constr_elem)
1532
		*pwr_reduction = *pwr_constr_elem;
1533 1534 1535
	else
		*pwr_reduction = 0;

1536 1537 1538
	return have_chan_pwr;
}

1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
static void ieee80211_find_cisco_dtpc(struct ieee80211_sub_if_data *sdata,
				      struct ieee80211_channel *channel,
				      const u8 *cisco_dtpc_ie,
				      int *pwr_level)
{
	/* From practical testing, the first data byte of the DTPC element
	 * seems to contain the requested dBm level, and the CLI on Cisco
	 * APs clearly state the range is -127 to 127 dBm, which indicates
	 * a signed byte, although it seemingly never actually goes negative.
	 * The other byte seems to always be zero.
	 */
	*pwr_level = (__s8)cisco_dtpc_ie[4];
}

1553 1554 1555 1556
static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
				       struct ieee80211_channel *channel,
				       struct ieee80211_mgmt *mgmt,
				       const u8 *country_ie, u8 country_ie_len,
1557 1558
				       const u8 *pwr_constr_ie,
				       const u8 *cisco_dtpc_ie)
1559
{
1560 1561 1562
	bool has_80211h_pwr = false, has_cisco_pwr = false;
	int chan_pwr = 0, pwr_reduction_80211h = 0;
	int pwr_level_cisco, pwr_level_80211h;
1563
	int new_ap_level;
1564
	__le16 capab = mgmt->u.probe_resp.capab_info;
1565

1566 1567 1568
	if (ieee80211_is_s1g_beacon(mgmt->frame_control))
		return 0;	/* TODO */

1569 1570 1571
	if (country_ie &&
	    (capab & cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT) ||
	     capab & cpu_to_le16(WLAN_CAPABILITY_RADIO_MEASURE))) {
1572 1573 1574
		has_80211h_pwr = ieee80211_find_80211h_pwr_constr(
			sdata, channel, country_ie, country_ie_len,
			pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h);
1575 1576 1577 1578 1579 1580 1581 1582
		pwr_level_80211h =
			max_t(int, 0, chan_pwr - pwr_reduction_80211h);
	}

	if (cisco_dtpc_ie) {
		ieee80211_find_cisco_dtpc(
			sdata, channel, cisco_dtpc_ie, &pwr_level_cisco);
		has_cisco_pwr = true;
1583
	}
1584

1585
	if (!has_80211h_pwr && !has_cisco_pwr)
1586
		return 0;
1587

1588 1589 1590 1591 1592
	/* If we have both 802.11h and Cisco DTPC, apply both limits
	 * by picking the smallest of the two power levels advertised.
	 */
	if (has_80211h_pwr &&
	    (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) {
1593 1594 1595 1596 1597
		new_ap_level = pwr_level_80211h;

		if (sdata->ap_power_level == new_ap_level)
			return 0;

1598 1599 1600 1601
		sdata_dbg(sdata,
			  "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
			  pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
			  sdata->u.mgd.bssid);
1602
	} else {  /* has_cisco_pwr is always true here. */
1603 1604 1605 1606 1607
		new_ap_level = pwr_level_cisco;

		if (sdata->ap_power_level == new_ap_level)
			return 0;

1608 1609 1610
		sdata_dbg(sdata,
			  "Limiting TX power to %d dBm as advertised by %pM\n",
			  pwr_level_cisco, sdata->u.mgd.bssid);
1611
	}
1612

1613 1614 1615 1616
	sdata->ap_power_level = new_ap_level;
	if (__ieee80211_recalc_txpower(sdata))
		return BSS_CHANGED_TXPOWER;
	return 0;
1617 1618
}

1619 1620 1621 1622 1623 1624
/* powersave */
static void ieee80211_enable_ps(struct ieee80211_local *local,
				struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_conf *conf = &local->hw.conf;

J
Johannes Berg 已提交
1625 1626 1627 1628
	/*
	 * If we are scanning right now then the parameters will
	 * take effect when scan finishes.
	 */
1629
	if (local->scanning)
J
Johannes Berg 已提交
1630 1631
		return;

1632
	if (conf->dynamic_ps_timeout > 0 &&
1633
	    !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) {
1634 1635 1636
		mod_timer(&local->dynamic_ps_timer, jiffies +
			  msecs_to_jiffies(conf->dynamic_ps_timeout));
	} else {
1637
		if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
1638
			ieee80211_send_nullfunc(local, sdata, true);
1639

1640 1641
		if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
		    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
1642 1643 1644 1645
			return;

		conf->flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662
	}
}

static void ieee80211_change_ps(struct ieee80211_local *local)
{
	struct ieee80211_conf *conf = &local->hw.conf;

	if (local->ps_sdata) {
		ieee80211_enable_ps(local, local->ps_sdata);
	} else if (conf->flags & IEEE80211_CONF_PS) {
		conf->flags &= ~IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
		del_timer_sync(&local->dynamic_ps_timer);
		cancel_work_sync(&local->dynamic_ps_enable_work);
	}
}

1663 1664 1665 1666
static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *mgd = &sdata->u.mgd;
	struct sta_info *sta = NULL;
J
Johannes Berg 已提交
1667
	bool authorized = false;
1668 1669 1670 1671

	if (!mgd->powersave)
		return false;

1672 1673 1674
	if (mgd->broken_ap)
		return false;

1675 1676 1677
	if (!mgd->associated)
		return false;

1678
	if (mgd->flags & IEEE80211_STA_CONNECTION_POLL)
1679 1680
		return false;

1681
	if (!mgd->have_beacon)
1682 1683
		return false;

1684 1685 1686
	rcu_read_lock();
	sta = sta_info_get(sdata, mgd->bssid);
	if (sta)
J
Johannes Berg 已提交
1687
		authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
1688 1689
	rcu_read_unlock();

J
Johannes Berg 已提交
1690
	return authorized;
1691 1692
}

1693
/* need to hold RTNL or interface lock */
J
Johannes Berg 已提交
1694
void ieee80211_recalc_ps(struct ieee80211_local *local)
1695 1696 1697
{
	struct ieee80211_sub_if_data *sdata, *found = NULL;
	int count = 0;
1698
	int timeout;
1699

1700
	if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS)) {
1701 1702 1703 1704 1705
		local->ps_sdata = NULL;
		return;
	}

	list_for_each_entry(sdata, &local->interfaces, list) {
1706
		if (!ieee80211_sdata_running(sdata))
1707
			continue;
1708 1709 1710 1711 1712 1713 1714 1715
		if (sdata->vif.type == NL80211_IFTYPE_AP) {
			/* If an AP vif is found, then disable PS
			 * by setting the count to zero thereby setting
			 * ps_sdata to NULL.
			 */
			count = 0;
			break;
		}
1716 1717 1718 1719 1720 1721
		if (sdata->vif.type != NL80211_IFTYPE_STATION)
			continue;
		found = sdata;
		count++;
	}

1722
	if (count == 1 && ieee80211_powersave_allowed(found)) {
J
Johannes Berg 已提交
1723
		u8 dtimper = found->u.mgd.dtim_period;
1724

1725
		timeout = local->dynamic_ps_forced_timeout;
J
Johannes Berg 已提交
1726 1727
		if (timeout < 0)
			timeout = 100;
1728
		local->hw.conf.dynamic_ps_timeout = timeout;
1729

J
Johannes Berg 已提交
1730 1731 1732 1733 1734 1735
		/* If the TIM IE is invalid, pretend the value is 1 */
		if (!dtimper)
			dtimper = 1;

		local->hw.conf.ps_dtim_period = dtimper;
		local->ps_sdata = found;
1736
	} else {
1737
		local->ps_sdata = NULL;
1738
	}
1739 1740 1741 1742

	ieee80211_change_ps(local);
}

E
Eliad Peller 已提交
1743 1744 1745 1746 1747 1748 1749 1750 1751 1752
void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata)
{
	bool ps_allowed = ieee80211_powersave_allowed(sdata);

	if (sdata->vif.bss_conf.ps != ps_allowed) {
		sdata->vif.bss_conf.ps = ps_allowed;
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_PS);
	}
}

1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764
void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     dynamic_ps_disable_work);

	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}

	ieee80211_wake_queues_by_reason(&local->hw,
1765
					IEEE80211_MAX_QUEUE_MAP,
1766 1767
					IEEE80211_QUEUE_STOP_REASON_PS,
					false);
1768 1769 1770 1771 1772 1773 1774 1775
}

void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     dynamic_ps_enable_work);
	struct ieee80211_sub_if_data *sdata = local->ps_sdata;
1776
	struct ieee80211_if_managed *ifmgd;
1777 1778
	unsigned long flags;
	int q;
1779 1780 1781 1782 1783

	/* can only happen when PS was just disabled anyway */
	if (!sdata)
		return;

1784 1785
	ifmgd = &sdata->u.mgd;

1786 1787 1788
	if (local->hw.conf.flags & IEEE80211_CONF_PS)
		return;

1789
	if (local->hw.conf.dynamic_ps_timeout > 0) {
1790 1791
		/* don't enter PS if TX frames are pending */
		if (drv_tx_frames_pending(local)) {
1792 1793 1794 1795 1796
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(
				  local->hw.conf.dynamic_ps_timeout));
			return;
		}
1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814

		/*
		 * transmission can be stopped by others which leads to
		 * dynamic_ps_timer expiry. Postpone the ps timer if it
		 * is not the actual idle state.
		 */
		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
		for (q = 0; q < local->hw.queues; q++) {
			if (local->queue_stop_reasons[q]) {
				spin_unlock_irqrestore(&local->queue_stop_reason_lock,
						       flags);
				mod_timer(&local->dynamic_ps_timer, jiffies +
					  msecs_to_jiffies(
					  local->hw.conf.dynamic_ps_timeout));
				return;
			}
		}
		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1815 1816
	}

1817
	if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
1818
	    !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
1819
		if (drv_tx_frames_pending(local)) {
1820 1821 1822
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(
				  local->hw.conf.dynamic_ps_timeout));
1823
		} else {
1824
			ieee80211_send_nullfunc(local, sdata, true);
1825
			/* Flush to get the tx status of nullfunc frame */
1826
			ieee80211_flush_queues(local, sdata, false);
1827
		}
1828 1829
	}

1830 1831
	if (!(ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) &&
	      ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) ||
1832 1833 1834 1835 1836
	    (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
		local->hw.conf.flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}
1837 1838
}

1839
void ieee80211_dynamic_ps_timer(struct timer_list *t)
1840
{
1841
	struct ieee80211_local *local = from_timer(local, t, dynamic_ps_timer);
1842

1843
	ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
1844 1845
}

1846 1847
void ieee80211_dfs_cac_timer_work(struct work_struct *work)
{
1848
	struct delayed_work *delayed_work = to_delayed_work(work);
1849 1850 1851
	struct ieee80211_sub_if_data *sdata =
		container_of(delayed_work, struct ieee80211_sub_if_data,
			     dfs_cac_timer_work);
1852
	struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
1853

1854 1855 1856 1857 1858 1859 1860 1861
	mutex_lock(&sdata->local->mtx);
	if (sdata->wdev.cac_started) {
		ieee80211_vif_release_channel(sdata);
		cfg80211_cac_event(sdata->dev, &chandef,
				   NL80211_RADAR_CAC_FINISHED,
				   GFP_KERNEL);
	}
	mutex_unlock(&sdata->local->mtx);
1862 1863
}

1864 1865 1866 1867 1868
static bool
__ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1869
	bool ret = false;
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
	int ac;

	if (local->hw.queues < IEEE80211_NUM_ACS)
		return false;

	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
		struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
		int non_acm_ac;
		unsigned long now = jiffies;

		if (tx_tspec->action == TX_TSPEC_ACTION_NONE &&
		    tx_tspec->admitted_time &&
		    time_after(now, tx_tspec->time_slice_start + HZ)) {
			tx_tspec->consumed_tx_time = 0;
			tx_tspec->time_slice_start = now;

			if (tx_tspec->downgraded)
				tx_tspec->action =
					TX_TSPEC_ACTION_STOP_DOWNGRADE;
		}

		switch (tx_tspec->action) {
		case TX_TSPEC_ACTION_STOP_DOWNGRADE:
			/* take the original parameters */
			if (drv_conf_tx(local, sdata, ac, &sdata->tx_conf[ac]))
				sdata_err(sdata,
					  "failed to set TX queue parameters for queue %d\n",
					  ac);
			tx_tspec->action = TX_TSPEC_ACTION_NONE;
			tx_tspec->downgraded = false;
			ret = true;
			break;
		case TX_TSPEC_ACTION_DOWNGRADE:
			if (time_after(now, tx_tspec->time_slice_start + HZ)) {
				tx_tspec->action = TX_TSPEC_ACTION_NONE;
				ret = true;
				break;
			}
			/* downgrade next lower non-ACM AC */
			for (non_acm_ac = ac + 1;
			     non_acm_ac < IEEE80211_NUM_ACS;
			     non_acm_ac++)
				if (!(sdata->wmm_acm & BIT(7 - 2 * non_acm_ac)))
					break;
1914 1915 1916 1917 1918 1919
			/* Usually the loop will result in using BK even if it
			 * requires admission control, but such a configuration
			 * makes no sense and we have to transmit somehow - the
			 * AC selection does the same thing.
			 * If we started out trying to downgrade from BK, then
			 * the extra condition here might be needed.
1920
			 */
1921 1922
			if (non_acm_ac >= IEEE80211_NUM_ACS)
				non_acm_ac = IEEE80211_AC_BK;
1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
			if (drv_conf_tx(local, sdata, ac,
					&sdata->tx_conf[non_acm_ac]))
				sdata_err(sdata,
					  "failed to set TX queue parameters for queue %d\n",
					  ac);
			tx_tspec->action = TX_TSPEC_ACTION_NONE;
			ret = true;
			schedule_delayed_work(&ifmgd->tx_tspec_wk,
				tx_tspec->time_slice_start + HZ - now + 1);
			break;
		case TX_TSPEC_ACTION_NONE:
			/* nothing now */
			break;
		}
	}

	return ret;
}

void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
{
	if (__ieee80211_sta_handle_tspec_ac_params(sdata))
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
}

static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata;

	sdata = container_of(work, struct ieee80211_sub_if_data,
			     u.mgd.tx_tspec_wk.work);
	ieee80211_sta_handle_tspec_ac_params(sdata);
}

J
Johannes Berg 已提交
1957
/* MLME */
L
Luca Coelho 已提交
1958 1959 1960 1961 1962
static bool
ieee80211_sta_wmm_params(struct ieee80211_local *local,
			 struct ieee80211_sub_if_data *sdata,
			 const u8 *wmm_param, size_t wmm_param_len,
			 const struct ieee80211_mu_edca_param_set *mu_edca)
1963
{
1964
	struct ieee80211_tx_queue_params params[IEEE80211_NUM_ACS];
1965
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1966
	size_t left;
1967
	int count, mu_edca_count, ac;
J
Johannes Berg 已提交
1968 1969
	const u8 *pos;
	u8 uapsd_queues = 0;
1970

1971
	if (!local->ops->conf_tx)
1972
		return false;
1973

J
Johannes Berg 已提交
1974
	if (local->hw.queues < IEEE80211_NUM_ACS)
1975
		return false;
1976 1977

	if (!wmm_param)
1978
		return false;
1979

1980
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
1981
		return false;
K
Kalle Valo 已提交
1982 1983

	if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
1984
		uapsd_queues = ifmgd->uapsd_queues;
K
Kalle Valo 已提交
1985

1986
	count = wmm_param[6] & 0x0f;
1987 1988 1989 1990 1991 1992 1993
	/* -1 is the initial value of ifmgd->mu_edca_last_param_set.
	 * if mu_edca was preset before and now it disappeared tell
	 * the driver about it.
	 */
	mu_edca_count = mu_edca ? mu_edca->mu_qos_info & 0x0f : -1;
	if (count == ifmgd->wmm_last_param_set &&
	    mu_edca_count == ifmgd->mu_edca_last_param_set)
1994
		return false;
1995
	ifmgd->wmm_last_param_set = count;
1996
	ifmgd->mu_edca_last_param_set = mu_edca_count;
1997 1998 1999 2000 2001 2002

	pos = wmm_param + 8;
	left = wmm_param_len - 8;

	memset(&params, 0, sizeof(params));

Y
Yoni Divinsky 已提交
2003
	sdata->wmm_acm = 0;
2004 2005 2006
	for (; left >= 4; left -= 4, pos += 4) {
		int aci = (pos[0] >> 5) & 0x03;
		int acm = (pos[0] >> 4) & 0x01;
K
Kalle Valo 已提交
2007
		bool uapsd = false;
2008 2009

		switch (aci) {
2010
		case 1: /* AC_BK */
2011
			ac = IEEE80211_AC_BK;
J
Johannes Berg 已提交
2012
			if (acm)
Y
Yoni Divinsky 已提交
2013
				sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
K
Kalle Valo 已提交
2014 2015
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
				uapsd = true;
L
Luca Coelho 已提交
2016 2017 2018
			params[ac].mu_edca = !!mu_edca;
			if (mu_edca)
				params[ac].mu_edca_param_rec = mu_edca->ac_bk;
2019
			break;
2020
		case 2: /* AC_VI */
2021
			ac = IEEE80211_AC_VI;
J
Johannes Berg 已提交
2022
			if (acm)
Y
Yoni Divinsky 已提交
2023
				sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
K
Kalle Valo 已提交
2024 2025
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
				uapsd = true;
L
Luca Coelho 已提交
2026 2027 2028
			params[ac].mu_edca = !!mu_edca;
			if (mu_edca)
				params[ac].mu_edca_param_rec = mu_edca->ac_vi;
2029
			break;
2030
		case 3: /* AC_VO */
2031
			ac = IEEE80211_AC_VO;
J
Johannes Berg 已提交
2032
			if (acm)
Y
Yoni Divinsky 已提交
2033
				sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
K
Kalle Valo 已提交
2034 2035
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
				uapsd = true;
L
Luca Coelho 已提交
2036 2037 2038
			params[ac].mu_edca = !!mu_edca;
			if (mu_edca)
				params[ac].mu_edca_param_rec = mu_edca->ac_vo;
2039
			break;
2040
		case 0: /* AC_BE */
2041
		default:
2042
			ac = IEEE80211_AC_BE;
J
Johannes Berg 已提交
2043
			if (acm)
Y
Yoni Divinsky 已提交
2044
				sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
K
Kalle Valo 已提交
2045 2046
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
				uapsd = true;
L
Luca Coelho 已提交
2047 2048 2049
			params[ac].mu_edca = !!mu_edca;
			if (mu_edca)
				params[ac].mu_edca_param_rec = mu_edca->ac_be;
2050 2051 2052
			break;
		}

2053
		params[ac].aifs = pos[0] & 0x0f;
2054

2055
		if (params[ac].aifs < 2) {
2056 2057
			sdata_info(sdata,
				   "AP has invalid WMM params (AIFSN=%d for ACI %d), will use 2\n",
2058 2059
				   params[ac].aifs, aci);
			params[ac].aifs = 2;
2060
		}
2061 2062 2063 2064 2065
		params[ac].cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params[ac].cw_min = ecw2cw(pos[1] & 0x0f);
		params[ac].txop = get_unaligned_le16(pos + 2);
		params[ac].acm = acm;
		params[ac].uapsd = uapsd;
K
Kalle Valo 已提交
2066

2067
		if (params[ac].cw_min == 0 ||
2068
		    params[ac].cw_min > params[ac].cw_max) {
2069 2070 2071 2072 2073
			sdata_info(sdata,
				   "AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n",
				   params[ac].cw_min, params[ac].cw_max, aci);
			return false;
		}
2074
		ieee80211_regulatory_limit_wmm_params(sdata, &params[ac], ac);
2075 2076
	}

2077 2078 2079 2080 2081 2082 2083 2084 2085 2086
	/* WMM specification requires all 4 ACIs. */
	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
		if (params[ac].cw_min == 0) {
			sdata_info(sdata,
				   "AP has invalid WMM params (missing AC %d), using defaults\n",
				   ac);
			return false;
		}
	}

2087
	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
J
Johannes Berg 已提交
2088
		mlme_dbg(sdata,
2089 2090 2091 2092 2093 2094 2095 2096
			 "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
			 ac, params[ac].acm,
			 params[ac].aifs, params[ac].cw_min, params[ac].cw_max,
			 params[ac].txop, params[ac].uapsd,
			 ifmgd->tx_tspec[ac].downgraded);
		sdata->tx_conf[ac] = params[ac];
		if (!ifmgd->tx_tspec[ac].downgraded &&
		    drv_conf_tx(local, sdata, ac, &params[ac]))
J
Johannes Berg 已提交
2097
			sdata_err(sdata,
2098 2099
				  "failed to set TX queue parameters for AC %d\n",
				  ac);
2100
	}
2101 2102

	/* enable WMM or activate new settings */
2103
	sdata->vif.bss_conf.qos = true;
2104
	return true;
2105 2106
}

2107 2108 2109 2110
static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)
{
	lockdep_assert_held(&sdata->local->mtx);

2111
	sdata->u.mgd.flags &= ~IEEE80211_STA_CONNECTION_POLL;
2112 2113 2114 2115 2116 2117 2118 2119 2120 2121
	ieee80211_run_deferred_scan(sdata->local);
}

static void ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)
{
	mutex_lock(&sdata->local->mtx);
	__ieee80211_stop_poll(sdata);
	mutex_unlock(&sdata->local->mtx);
}

J
Johannes Berg 已提交
2122 2123
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
2124
{
J
Johannes Berg 已提交
2125
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
2126
	struct ieee80211_supported_band *sband;
2127
	u32 changed = 0;
J
Johannes Berg 已提交
2128 2129 2130 2131
	bool use_protection;
	bool use_short_preamble;
	bool use_short_slot;

2132 2133 2134 2135
	sband = ieee80211_get_sband(sdata);
	if (!sband)
		return changed;

J
Johannes Berg 已提交
2136 2137 2138 2139 2140 2141 2142 2143 2144
	if (erp_valid) {
		use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0;
		use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0;
	} else {
		use_protection = false;
		use_short_preamble = !!(capab & WLAN_CAPABILITY_SHORT_PREAMBLE);
	}

	use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
2145 2146
	if (sband->band == NL80211_BAND_5GHZ ||
	    sband->band == NL80211_BAND_6GHZ)
2147
		use_short_slot = true;
2148

2149 2150 2151
	if (use_protection != bss_conf->use_cts_prot) {
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
2152
	}
2153

2154 2155
	if (use_short_preamble != bss_conf->use_short_preamble) {
		bss_conf->use_short_preamble = use_short_preamble;
2156
		changed |= BSS_CHANGED_ERP_PREAMBLE;
2157
	}
2158

J
Johannes Berg 已提交
2159 2160 2161
	if (use_short_slot != bss_conf->use_short_slot) {
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
2162 2163 2164 2165 2166
	}

	return changed;
}

2167
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
2168
				     struct cfg80211_bss *cbss,
J
Johannes Berg 已提交
2169
				     u32 bss_info_changed)
2170
{
2171
	struct ieee80211_bss *bss = (void *)cbss->priv;
2172
	struct ieee80211_local *local = sdata->local;
2173
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
2174

J
Johannes Berg 已提交
2175
	bss_info_changed |= BSS_CHANGED_ASSOC;
2176
	bss_info_changed |= ieee80211_handle_bss_capability(sdata,
2177
		bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
2178

2179
	sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
2180
		beacon_loss_count * bss_conf->beacon_int));
2181

2182 2183
	sdata->u.mgd.associated = cbss;
	memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
2184

2185 2186
	ieee80211_check_rate_mask(sdata);

2187 2188
	sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;

2189 2190
	if (sdata->vif.p2p ||
	    sdata->vif.driver_flags & IEEE80211_VIF_GET_NOA_UPDATE) {
2191
		const struct cfg80211_bss_ies *ies;
2192

2193 2194 2195 2196 2197 2198 2199 2200
		rcu_read_lock();
		ies = rcu_dereference(cbss->ies);
		if (ies) {
			int ret;

			ret = cfg80211_get_p2p_attr(
					ies->data, ies->len,
					IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
J
Janusz Dziedzic 已提交
2201 2202
					(u8 *) &bss_conf->p2p_noa_attr,
					sizeof(bss_conf->p2p_noa_attr));
2203
			if (ret >= 2) {
J
Janusz Dziedzic 已提交
2204 2205
				sdata->u.mgd.p2p_noa_index =
					bss_conf->p2p_noa_attr.index;
2206 2207
				bss_info_changed |= BSS_CHANGED_P2P_PS;
			}
2208
		}
2209
		rcu_read_unlock();
2210 2211
	}

J
Johannes Berg 已提交
2212
	/* just to be sure */
2213
	ieee80211_stop_poll(sdata);
J
Johannes Berg 已提交
2214

2215
	ieee80211_led_assoc(local, 1);
2216

2217
	if (sdata->u.mgd.have_beacon) {
2218 2219 2220 2221 2222 2223 2224
		/*
		 * If the AP is buggy we may get here with no DTIM period
		 * known, so assume it's 1 which is the only safe assumption
		 * in that case, although if the TIM IE is broken powersave
		 * probably just won't work at all.
		 */
		bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1;
2225
		bss_conf->beacon_rate = bss->beacon_rate;
2226
		bss_info_changed |= BSS_CHANGED_BEACON_INFO;
2227
	} else {
2228
		bss_conf->beacon_rate = NULL;
2229
		bss_conf->dtim_period = 0;
2230
	}
2231

2232
	bss_conf->assoc = 1;
2233

2234
	/* Tell the driver to monitor connection quality (if supported) */
2235
	if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI &&
2236
	    bss_conf->cqm_rssi_thold)
2237 2238
		bss_info_changed |= BSS_CHANGED_CQM;

2239
	/* Enable ARP filtering */
2240
	if (bss_conf->arp_addr_cnt)
2241 2242
		bss_info_changed |= BSS_CHANGED_ARP_FILTER;

J
Johannes Berg 已提交
2243
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
2244

J
Johannes Berg 已提交
2245
	mutex_lock(&local->iflist_mtx);
J
Johannes Berg 已提交
2246
	ieee80211_recalc_ps(local);
J
Johannes Berg 已提交
2247
	mutex_unlock(&local->iflist_mtx);
2248

2249
	ieee80211_recalc_smps(sdata);
E
Eliad Peller 已提交
2250 2251
	ieee80211_recalc_ps_vif(sdata);

2252
	netif_carrier_on(sdata->dev);
2253 2254
}

2255
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
2256 2257
				   u16 stype, u16 reason, bool tx,
				   u8 *frame_buf)
2258
{
2259
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2260
	struct ieee80211_local *local = sdata->local;
2261
	u32 changed = 0;
2262 2263 2264
	struct ieee80211_prep_tx_info info = {
		.subtype = stype,
	};
2265

2266
	sdata_assert_lock(sdata);
2267

2268 2269 2270
	if (WARN_ON_ONCE(tx && !frame_buf))
		return;

J
Johannes Berg 已提交
2271 2272 2273
	if (WARN_ON(!ifmgd->associated))
		return;

2274 2275
	ieee80211_stop_poll(sdata);

2276
	ifmgd->associated = NULL;
2277 2278
	netif_carrier_off(sdata->dev);

2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289
	/*
	 * if we want to get out of ps before disassoc (why?) we have
	 * to do it before sending disassoc, as otherwise the null-packet
	 * won't be valid.
	 */
	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}
	local->ps_sdata = NULL;

E
Eliad Peller 已提交
2290 2291 2292
	/* disable per-vif ps */
	ieee80211_recalc_ps_vif(sdata);

2293 2294 2295
	/* make sure ongoing transmission finishes */
	synchronize_net();

2296 2297 2298 2299 2300 2301
	/*
	 * drop any frame before deauth/disassoc, this can be data or
	 * management frame. Since we are disconnecting, we should not
	 * insist sending these frames which can take time and delay
	 * the disconnection and possible the roaming.
	 */
2302
	if (tx)
2303
		ieee80211_flush_queues(local, sdata, true);
2304

2305
	/* deauthenticate/disassociate now */
2306 2307 2308 2309 2310 2311 2312 2313
	if (tx || frame_buf) {
		/*
		 * In multi channel scenarios guarantee that the virtual
		 * interface is granted immediate airtime to transmit the
		 * deauthentication frame by calling mgd_prepare_tx, if the
		 * driver requested so.
		 */
		if (ieee80211_hw_check(&local->hw, DEAUTH_NEED_MGD_TX_PREP) &&
2314 2315 2316
		    !ifmgd->have_beacon) {
			drv_mgd_prepare_tx(sdata->local, sdata, &info);
		}
2317

2318 2319 2320
		ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid,
					       ifmgd->bssid, stype, reason,
					       tx, frame_buf);
2321
	}
2322

2323
	/* flush out frame - make sure the deauth was actually sent */
2324
	if (tx)
2325
		ieee80211_flush_queues(local, sdata, false);
2326

2327 2328
	drv_mgd_complete_tx(sdata->local, sdata, &info);

2329
	/* clear bssid only after building the needed mgmt frames */
2330
	eth_zero_addr(ifmgd->bssid);
2331

2332 2333
	sdata->vif.bss_conf.ssid_len = 0;

2334
	/* remove AP and TDLS peers */
2335
	sta_info_flush(sdata);
2336 2337

	/* finally reset all BSS / config parameters */
2338 2339 2340
	changed |= ieee80211_reset_erp_info(sdata);

	ieee80211_led_assoc(local, 0);
J
Johannes Berg 已提交
2341 2342
	changed |= BSS_CHANGED_ASSOC;
	sdata->vif.bss_conf.assoc = false;
2343

J
Janusz Dziedzic 已提交
2344 2345 2346
	ifmgd->p2p_noa_index = -1;
	memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
	       sizeof(sdata->vif.bss_conf.p2p_noa_attr));
2347

2348
	/* on the next assoc, re-program HT/VHT parameters */
B
Ben Greear 已提交
2349 2350
	memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
	memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
2351 2352
	memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
	memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
2353 2354 2355 2356 2357 2358 2359

	/* reset MU-MIMO ownership and group data */
	memset(sdata->vif.bss_conf.mu_group.membership, 0,
	       sizeof(sdata->vif.bss_conf.mu_group.membership));
	memset(sdata->vif.bss_conf.mu_group.position, 0,
	       sizeof(sdata->vif.bss_conf.mu_group.position));
	changed |= BSS_CHANGED_MU_GROUPS;
2360
	sdata->vif.mu_mimo_owner = false;
2361

2362
	sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
2363

2364 2365 2366
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

2367
	/* Disable ARP filtering */
2368
	if (sdata->vif.bss_conf.arp_addr_cnt)
2369 2370
		changed |= BSS_CHANGED_ARP_FILTER;

2371 2372 2373
	sdata->vif.bss_conf.qos = false;
	changed |= BSS_CHANGED_QOS;

2374 2375
	/* The BSSID (not really interesting) and HT changed */
	changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
J
Johannes Berg 已提交
2376
	ieee80211_bss_info_change_notify(sdata, changed);
2377

2378
	/* disassociated - set to defaults now */
2379
	ieee80211_set_wmm_default(sdata, false, false);
2380

2381 2382 2383 2384
	del_timer_sync(&sdata->u.mgd.conn_mon_timer);
	del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
	del_timer_sync(&sdata->u.mgd.timer);
	del_timer_sync(&sdata->u.mgd.chswitch_timer);
2385

2386
	sdata->vif.bss_conf.dtim_period = 0;
2387 2388
	sdata->vif.bss_conf.beacon_rate = NULL;

2389
	ifmgd->have_beacon = false;
2390

2391
	ifmgd->flags = 0;
2392
	mutex_lock(&local->mtx);
2393
	ieee80211_vif_release_channel(sdata);
2394 2395

	sdata->vif.csa_active = false;
2396
	ifmgd->csa_waiting_bcn = false;
2397
	ifmgd->csa_ignored_same_chan = false;
2398 2399 2400 2401 2402
	if (sdata->csa_block_tx) {
		ieee80211_wake_vif_queues(local, sdata,
					  IEEE80211_QUEUE_STOP_REASON_CSA);
		sdata->csa_block_tx = false;
	}
2403
	mutex_unlock(&local->mtx);
2404

2405 2406 2407 2408
	/* existing TX TSPEC sessions no longer exist */
	memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec));
	cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);

2409
	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
2410
}
2411

2412 2413 2414
static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2415
	struct ieee80211_local *local = sdata->local;
2416

2417
	mutex_lock(&local->mtx);
2418 2419
	if (!(ifmgd->flags & IEEE80211_STA_CONNECTION_POLL))
		goto out;
2420

2421
	__ieee80211_stop_poll(sdata);
2422 2423

	mutex_lock(&local->iflist_mtx);
J
Johannes Berg 已提交
2424
	ieee80211_recalc_ps(local);
2425
	mutex_unlock(&local->iflist_mtx);
2426

2427
	if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
2428
		goto out;
2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439

	/*
	 * We've received a probe response, but are not sure whether
	 * we have or will be receiving any beacons or data, so let's
	 * schedule the timers again, just in case.
	 */
	ieee80211_sta_reset_beacon_monitor(sdata);

	mod_timer(&ifmgd->conn_mon_timer,
		  round_jiffies_up(jiffies +
				   IEEE80211_CONNECTION_IDLE_TIME));
2440 2441
out:
	mutex_unlock(&local->mtx);
2442 2443
}

2444 2445 2446 2447 2448
static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
					   struct ieee80211_hdr *hdr,
					   u16 tx_time)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
S
Sara Sharon 已提交
2449
	u16 tid = ieee80211_get_tid(hdr);
2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478
	int ac = ieee80211_ac_from_tid(tid);
	struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
	unsigned long now = jiffies;

	if (likely(!tx_tspec->admitted_time))
		return;

	if (time_after(now, tx_tspec->time_slice_start + HZ)) {
		tx_tspec->consumed_tx_time = 0;
		tx_tspec->time_slice_start = now;

		if (tx_tspec->downgraded) {
			tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
			schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
		}
	}

	if (tx_tspec->downgraded)
		return;

	tx_tspec->consumed_tx_time += tx_time;

	if (tx_tspec->consumed_tx_time >= tx_tspec->admitted_time) {
		tx_tspec->downgraded = true;
		tx_tspec->action = TX_TSPEC_ACTION_DOWNGRADE;
		schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
	}
}

2479
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
2480
			     struct ieee80211_hdr *hdr, bool ack, u16 tx_time)
2481
{
2482 2483
	ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);

2484 2485
	if (!ieee80211_is_any_nullfunc(hdr->frame_control) ||
	    !sdata->u.mgd.probe_send_count)
2486 2487
		return;

2488 2489 2490
	if (ack)
		sdata->u.mgd.probe_send_count = 0;
	else
2491 2492
		sdata->u.mgd.nullfunc_failed = true;
	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
2493 2494
}

2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508
static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
					  const u8 *src, const u8 *dst,
					  const u8 *ssid, size_t ssid_len,
					  struct ieee80211_channel *channel)
{
	struct sk_buff *skb;

	skb = ieee80211_build_probe_req(sdata, src, dst, (u32)-1, channel,
					ssid, ssid_len, NULL, 0,
					IEEE80211_PROBE_FLAG_DIRECTED);
	if (skb)
		ieee80211_tx_skb(sdata, skb);
}

2509 2510 2511 2512
static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	const u8 *ssid;
2513
	u8 *dst = ifmgd->associated->bssid;
2514
	u8 unicast_limit = max(1, max_probe_tries - 3);
J
Johannes Berg 已提交
2515
	struct sta_info *sta;
2516 2517 2518 2519 2520 2521 2522 2523

	/*
	 * Try sending broadcast probe requests for the last three
	 * probe requests after the first ones failed since some
	 * buggy APs only support broadcast probe requests.
	 */
	if (ifmgd->probe_send_count >= unicast_limit)
		dst = NULL;
2524

2525 2526 2527 2528 2529 2530 2531
	/*
	 * When the hardware reports an accurate Tx ACK status, it's
	 * better to send a nullfunc frame instead of a probe request,
	 * as it will kick us off the AP quickly if we aren't associated
	 * anymore. The timeout will be reset if the frame is ACKed by
	 * the AP.
	 */
2532 2533
	ifmgd->probe_send_count++;

J
Johannes Berg 已提交
2534 2535 2536 2537 2538 2539 2540 2541
	if (dst) {
		mutex_lock(&sdata->local->sta_mtx);
		sta = sta_info_get(sdata, dst);
		if (!WARN_ON(!sta))
			ieee80211_check_fast_rx(sta);
		mutex_unlock(&sdata->local->sta_mtx);
	}

2542
	if (ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) {
2543
		ifmgd->nullfunc_failed = false;
2544
		ieee80211_send_nullfunc(sdata->local, sdata, false);
2545
	} else {
2546 2547
		int ssid_len;

2548
		rcu_read_lock();
2549
		ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
2550 2551 2552 2553 2554
		if (WARN_ON_ONCE(ssid == NULL))
			ssid_len = 0;
		else
			ssid_len = ssid[1];

2555 2556 2557
		ieee80211_mlme_send_probe_req(sdata, sdata->vif.addr, dst,
					      ssid + 2, ssid_len,
					      ifmgd->associated->channel);
2558
		rcu_read_unlock();
2559
	}
2560

2561
	ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
2562
	run_again(sdata, ifmgd->probe_timeout);
2563 2564
}

J
Johannes Berg 已提交
2565 2566
static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
				   bool beacon)
2567 2568
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
2569
	bool already = false;
2570

2571
	if (!ieee80211_sdata_running(sdata))
2572 2573
		return;

2574
	sdata_lock(sdata);
2575 2576 2577 2578

	if (!ifmgd->associated)
		goto out;

2579 2580 2581 2582 2583 2584 2585
	mutex_lock(&sdata->local->mtx);

	if (sdata->local->tmp_channel || sdata->local->scanning) {
		mutex_unlock(&sdata->local->mtx);
		goto out;
	}

2586
	if (beacon) {
J
Johannes Berg 已提交
2587
		mlme_dbg_ratelimited(sdata,
2588 2589
				     "detected beacon loss from AP (missed %d beacons) - probing\n",
				     beacon_loss_count);
J
Johannes Berg 已提交
2590

2591
		ieee80211_cqm_beacon_loss_notify(&sdata->vif, GFP_KERNEL);
2592
	}
2593

J
Johannes Berg 已提交
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604
	/*
	 * The driver/our work has already reported this event or the
	 * connection monitoring has kicked in and we have already sent
	 * a probe request. Or maybe the AP died and the driver keeps
	 * reporting until we disassociate...
	 *
	 * In either case we have to ignore the current call to this
	 * function (except for setting the correct probe reason bit)
	 * because otherwise we would reset the timer every time and
	 * never check whether we received a probe response!
	 */
2605
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
J
Johannes Berg 已提交
2606 2607
		already = true;

E
Eliad Peller 已提交
2608 2609
	ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;

2610 2611
	mutex_unlock(&sdata->local->mtx);

J
Johannes Berg 已提交
2612 2613 2614
	if (already)
		goto out;

2615
	mutex_lock(&sdata->local->iflist_mtx);
J
Johannes Berg 已提交
2616
	ieee80211_recalc_ps(sdata->local);
2617 2618
	mutex_unlock(&sdata->local->iflist_mtx);

2619 2620
	ifmgd->probe_send_count = 0;
	ieee80211_mgd_probe_ap_send(sdata);
2621
 out:
2622
	sdata_unlock(sdata);
2623 2624
}

2625 2626 2627 2628 2629
struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
					  struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2630
	struct cfg80211_bss *cbss;
2631 2632
	struct sk_buff *skb;
	const u8 *ssid;
2633
	int ssid_len;
2634 2635 2636 2637

	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
		return NULL;

2638
	sdata_assert_lock(sdata);
2639

2640 2641 2642 2643 2644 2645 2646
	if (ifmgd->associated)
		cbss = ifmgd->associated;
	else if (ifmgd->auth_data)
		cbss = ifmgd->auth_data->bss;
	else if (ifmgd->assoc_data)
		cbss = ifmgd->assoc_data->bss;
	else
2647 2648
		return NULL;

2649
	rcu_read_lock();
2650
	ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
2651 2652
	if (WARN_ONCE(!ssid || ssid[1] > IEEE80211_MAX_SSID_LEN,
		      "invalid SSID element (len=%d)", ssid ? ssid[1] : -1))
2653 2654 2655 2656
		ssid_len = 0;
	else
		ssid_len = ssid[1];

2657
	skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid,
J
Johannes Berg 已提交
2658
					(u32) -1, cbss->channel,
2659
					ssid + 2, ssid_len,
2660
					NULL, 0, IEEE80211_PROBE_FLAG_DIRECTED);
2661
	rcu_read_unlock();
2662 2663 2664 2665 2666

	return skb;
}
EXPORT_SYMBOL(ieee80211_ap_probereq_get);

2667 2668
static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata,
					const u8 *buf, size_t len, bool tx,
2669
					u16 reason, bool reconnect)
2670 2671 2672 2673 2674 2675 2676 2677
{
	struct ieee80211_event event = {
		.type = MLME_EVENT,
		.u.mlme.data = tx ? DEAUTH_TX_EVENT : DEAUTH_RX_EVENT,
		.u.mlme.reason = reason,
	};

	if (tx)
2678
		cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, reconnect);
2679 2680 2681 2682 2683 2684
	else
		cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);

	drv_event_callback(sdata->local, sdata, &event);
}

2685
static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2686
{
2687
	struct ieee80211_local *local = sdata->local;
2688
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2689
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
2690
	bool tx;
2691

2692
	sdata_lock(sdata);
2693
	if (!ifmgd->associated) {
2694
		sdata_unlock(sdata);
2695 2696 2697
		return;
	}

2698 2699
	tx = !sdata->csa_block_tx;

2700 2701 2702 2703 2704 2705 2706
	if (!ifmgd->driver_disconnect) {
		/*
		 * AP is probably out of range (or not reachable for another
		 * reason) so remove the bss struct for that AP.
		 */
		cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated);
	}
2707

2708
	ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
2709 2710 2711
			       ifmgd->driver_disconnect ?
					WLAN_REASON_DEAUTH_LEAVING :
					WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
2712
			       tx, frame_buf);
2713
	mutex_lock(&local->mtx);
2714
	sdata->vif.csa_active = false;
2715
	ifmgd->csa_waiting_bcn = false;
2716 2717 2718 2719 2720
	if (sdata->csa_block_tx) {
		ieee80211_wake_vif_queues(local, sdata,
					  IEEE80211_QUEUE_STOP_REASON_CSA);
		sdata->csa_block_tx = false;
	}
2721
	mutex_unlock(&local->mtx);
2722

2723
	ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx,
2724 2725 2726
				    WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
				    ifmgd->reconnect);
	ifmgd->reconnect = false;
2727

2728
	sdata_unlock(sdata);
2729 2730
}

2731
static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
J
Johannes Berg 已提交
2732 2733 2734
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data,
2735
			     u.mgd.beacon_connection_loss_work);
2736 2737
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

2738 2739
	if (ifmgd->associated)
		ifmgd->beacon_loss_count++;
J
Johannes Berg 已提交
2740

2741
	if (ifmgd->connection_loss) {
2742 2743
		sdata_info(sdata, "Connection to AP %pM lost\n",
			   ifmgd->bssid);
2744
		__ieee80211_disconnect(sdata);
2745 2746 2747 2748 2749 2750 2751
		ifmgd->connection_loss = false;
	} else if (ifmgd->driver_disconnect) {
		sdata_info(sdata,
			   "Driver requested disconnection from AP %pM\n",
			   ifmgd->bssid);
		__ieee80211_disconnect(sdata);
		ifmgd->driver_disconnect = false;
2752
	} else {
2753
		ieee80211_mgd_probe_ap(sdata, true);
2754 2755 2756 2757 2758 2759 2760 2761 2762
	}
}

static void ieee80211_csa_connection_drop_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data,
			     u.mgd.csa_connection_drop_work);

2763
	__ieee80211_disconnect(sdata);
J
Johannes Berg 已提交
2764 2765
}

2766 2767 2768
void ieee80211_beacon_loss(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2769
	struct ieee80211_hw *hw = &sdata->local->hw;
2770

J
Johannes Berg 已提交
2771 2772
	trace_api_beacon_loss(sdata);

2773
	sdata->u.mgd.connection_loss = false;
2774
	ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
2775 2776 2777
}
EXPORT_SYMBOL(ieee80211_beacon_loss);

2778 2779 2780 2781 2782
void ieee80211_connection_loss(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_hw *hw = &sdata->local->hw;

J
Johannes Berg 已提交
2783 2784
	trace_api_connection_loss(sdata);

2785
	sdata->u.mgd.connection_loss = true;
2786 2787 2788 2789
	ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
}
EXPORT_SYMBOL(ieee80211_connection_loss);

2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804
void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_hw *hw = &sdata->local->hw;

	trace_api_disconnect(sdata, reconnect);

	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
		return;

	sdata->u.mgd.driver_disconnect = true;
	sdata->u.mgd.reconnect = reconnect;
	ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
}
EXPORT_SYMBOL(ieee80211_disconnect);
2805

J
Johannes Berg 已提交
2806 2807 2808 2809 2810
static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
					bool assoc)
{
	struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;

2811
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
2812 2813

	if (!assoc) {
2814 2815 2816 2817 2818 2819
		/*
		 * we are not authenticated yet, the only timer that could be
		 * running is the timeout for the authentication response which
		 * which is not relevant anymore.
		 */
		del_timer_sync(&sdata->u.mgd.timer);
J
Johannes Berg 已提交
2820 2821
		sta_info_destroy_addr(sdata, auth_data->bss->bssid);

2822
		eth_zero_addr(sdata->u.mgd.bssid);
J
Johannes Berg 已提交
2823
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2824
		sdata->u.mgd.flags = 0;
2825
		mutex_lock(&sdata->local->mtx);
J
Johannes Berg 已提交
2826
		ieee80211_vif_release_channel(sdata);
2827
		mutex_unlock(&sdata->local->mtx);
J
Johannes Berg 已提交
2828 2829
	}

2830
	cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
J
Johannes Berg 已提交
2831 2832 2833 2834
	kfree(auth_data);
	sdata->u.mgd.auth_data = NULL;
}

2835
static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2836
					 bool assoc, bool abandon)
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853
{
	struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;

	sdata_assert_lock(sdata);

	if (!assoc) {
		/*
		 * we are not associated yet, the only timer that could be
		 * running is the timeout for the association response which
		 * which is not relevant anymore.
		 */
		del_timer_sync(&sdata->u.mgd.timer);
		sta_info_destroy_addr(sdata, assoc_data->bss->bssid);

		eth_zero_addr(sdata->u.mgd.bssid);
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
		sdata->u.mgd.flags = 0;
2854 2855
		sdata->vif.mu_mimo_owner = false;

2856 2857 2858
		mutex_lock(&sdata->local->mtx);
		ieee80211_vif_release_channel(sdata);
		mutex_unlock(&sdata->local->mtx);
2859 2860 2861

		if (abandon)
			cfg80211_abandon_assoc(sdata->dev, assoc_data->bss);
2862 2863 2864 2865 2866 2867
	}

	kfree(assoc_data);
	sdata->u.mgd.assoc_data = NULL;
}

J
Johannes Berg 已提交
2868 2869 2870
static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_mgmt *mgmt, size_t len)
{
2871
	struct ieee80211_local *local = sdata->local;
J
Johannes Berg 已提交
2872 2873 2874
	struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
	u8 *pos;
	struct ieee802_11_elems elems;
2875
	u32 tx_flags = 0;
2876 2877 2878
	struct ieee80211_prep_tx_info info = {
		.subtype = IEEE80211_STYPE_AUTH,
	};
J
Johannes Berg 已提交
2879 2880

	pos = mgmt->u.auth.variable;
2881 2882
	ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
			       mgmt->bssid, auth_data->bss->bssid);
J
Johannes Berg 已提交
2883 2884 2885
	if (!elems.challenge)
		return;
	auth_data->expected_transaction = 4;
2886
	drv_mgd_prepare_tx(sdata->local, sdata, &info);
2887
	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
2888 2889
		tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
			   IEEE80211_TX_INTFL_MLME_CONN_TX;
2890
	ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0,
J
Johannes Berg 已提交
2891 2892 2893
			    elems.challenge - 2, elems.challenge_len + 2,
			    auth_data->bss->bssid, auth_data->bss->bssid,
			    auth_data->key, auth_data->key_len,
2894
			    auth_data->key_idx, tx_flags);
J
Johannes Berg 已提交
2895 2896
}

2897 2898 2899
static bool ieee80211_mark_sta_auth(struct ieee80211_sub_if_data *sdata,
				    const u8 *bssid)
{
2900
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2901
	struct sta_info *sta;
2902
	bool result = true;
2903

2904 2905 2906 2907 2908 2909
	sdata_info(sdata, "authenticated\n");
	ifmgd->auth_data->done = true;
	ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
	ifmgd->auth_data->timeout_started = true;
	run_again(sdata, ifmgd->auth_data->timeout);

2910 2911 2912 2913 2914
	/* move station state to auth */
	mutex_lock(&sdata->local->sta_mtx);
	sta = sta_info_get(sdata, bssid);
	if (!sta) {
		WARN_ONCE(1, "%s: STA %pM not found", sdata->name, bssid);
2915 2916
		result = false;
		goto out;
2917 2918 2919
	}
	if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) {
		sdata_info(sdata, "failed moving %pM to auth\n", bssid);
2920 2921
		result = false;
		goto out;
2922 2923
	}

2924 2925 2926
out:
	mutex_unlock(&sdata->local->sta_mtx);
	return result;
2927 2928
}

2929 2930
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_mgmt *mgmt, size_t len)
J
Johannes Berg 已提交
2931 2932 2933 2934
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	u8 bssid[ETH_ALEN];
	u16 auth_alg, auth_transaction, status_code;
2935 2936 2937 2938
	struct ieee80211_event event = {
		.type = MLME_EVENT,
		.u.mlme.data = AUTH_EVENT,
	};
2939 2940 2941
	struct ieee80211_prep_tx_info info = {
		.subtype = IEEE80211_STYPE_AUTH,
	};
J
Johannes Berg 已提交
2942

2943
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
2944 2945

	if (len < 24 + 6)
2946
		return;
J
Johannes Berg 已提交
2947 2948

	if (!ifmgd->auth_data || ifmgd->auth_data->done)
2949
		return;
J
Johannes Berg 已提交
2950 2951 2952

	memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);

2953
	if (!ether_addr_equal(bssid, mgmt->bssid))
2954
		return;
J
Johannes Berg 已提交
2955 2956 2957 2958 2959 2960

	auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
	auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
	status_code = le16_to_cpu(mgmt->u.auth.status_code);

	if (auth_alg != ifmgd->auth_data->algorithm ||
2961 2962 2963 2964 2965
	    (auth_alg != WLAN_AUTH_SAE &&
	     auth_transaction != ifmgd->auth_data->expected_transaction) ||
	    (auth_alg == WLAN_AUTH_SAE &&
	     (auth_transaction < ifmgd->auth_data->expected_transaction ||
	      auth_transaction > 2))) {
2966 2967 2968 2969
		sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",
			   mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
			   auth_transaction,
			   ifmgd->auth_data->expected_transaction);
2970
		goto notify_driver;
2971
	}
J
Johannes Berg 已提交
2972 2973

	if (status_code != WLAN_STATUS_SUCCESS) {
2974 2975 2976
		cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);

		if (auth_alg == WLAN_AUTH_SAE &&
2977 2978 2979 2980
		    (status_code == WLAN_STATUS_ANTI_CLOG_REQUIRED ||
		     (auth_transaction == 1 &&
		      (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
		       status_code == WLAN_STATUS_SAE_PK))))
2981
			goto notify_driver;
2982

J
Johannes Berg 已提交
2983 2984
		sdata_info(sdata, "%pM denied authentication (status %d)\n",
			   mgmt->sa, status_code);
2985
		ieee80211_destroy_auth_data(sdata, false);
2986 2987 2988
		event.u.mlme.status = MLME_DENIED;
		event.u.mlme.reason = status_code;
		drv_event_callback(sdata->local, sdata, &event);
2989
		goto notify_driver;
J
Johannes Berg 已提交
2990 2991 2992 2993 2994 2995
	}

	switch (ifmgd->auth_data->algorithm) {
	case WLAN_AUTH_OPEN:
	case WLAN_AUTH_LEAP:
	case WLAN_AUTH_FT:
2996
	case WLAN_AUTH_SAE:
2997 2998 2999
	case WLAN_AUTH_FILS_SK:
	case WLAN_AUTH_FILS_SK_PFS:
	case WLAN_AUTH_FILS_PK:
J
Johannes Berg 已提交
3000 3001 3002 3003 3004
		break;
	case WLAN_AUTH_SHARED_KEY:
		if (ifmgd->auth_data->expected_transaction != 4) {
			ieee80211_auth_challenge(sdata, mgmt, len);
			/* need another frame */
3005
			return;
J
Johannes Berg 已提交
3006 3007 3008 3009 3010
		}
		break;
	default:
		WARN_ONCE(1, "invalid auth alg %d",
			  ifmgd->auth_data->algorithm);
3011
		goto notify_driver;
J
Johannes Berg 已提交
3012 3013
	}

3014
	event.u.mlme.status = MLME_SUCCESS;
3015
	info.success = 1;
3016
	drv_event_callback(sdata->local, sdata, &event);
3017 3018 3019 3020
	if (ifmgd->auth_data->algorithm != WLAN_AUTH_SAE ||
	    (auth_transaction == 2 &&
	     ifmgd->auth_data->expected_transaction == 2)) {
		if (!ieee80211_mark_sta_auth(sdata, bssid))
3021
			return; /* ignore frame -- wait for timeout */
3022 3023 3024 3025
	} else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
		   auth_transaction == 2) {
		sdata_info(sdata, "SAE peer confirmed\n");
		ifmgd->auth_data->peer_confirmed = true;
3026 3027
	}

3028
	cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
3029 3030
notify_driver:
	drv_mgd_complete_tx(sdata->local, sdata, &info);
J
Johannes Berg 已提交
3031 3032
}

3033 3034 3035
#define case_WLAN(type) \
	case WLAN_REASON_##type: return #type

3036
const char *ieee80211_get_reason_code_string(u16 reason_code)
3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088
{
	switch (reason_code) {
	case_WLAN(UNSPECIFIED);
	case_WLAN(PREV_AUTH_NOT_VALID);
	case_WLAN(DEAUTH_LEAVING);
	case_WLAN(DISASSOC_DUE_TO_INACTIVITY);
	case_WLAN(DISASSOC_AP_BUSY);
	case_WLAN(CLASS2_FRAME_FROM_NONAUTH_STA);
	case_WLAN(CLASS3_FRAME_FROM_NONASSOC_STA);
	case_WLAN(DISASSOC_STA_HAS_LEFT);
	case_WLAN(STA_REQ_ASSOC_WITHOUT_AUTH);
	case_WLAN(DISASSOC_BAD_POWER);
	case_WLAN(DISASSOC_BAD_SUPP_CHAN);
	case_WLAN(INVALID_IE);
	case_WLAN(MIC_FAILURE);
	case_WLAN(4WAY_HANDSHAKE_TIMEOUT);
	case_WLAN(GROUP_KEY_HANDSHAKE_TIMEOUT);
	case_WLAN(IE_DIFFERENT);
	case_WLAN(INVALID_GROUP_CIPHER);
	case_WLAN(INVALID_PAIRWISE_CIPHER);
	case_WLAN(INVALID_AKMP);
	case_WLAN(UNSUPP_RSN_VERSION);
	case_WLAN(INVALID_RSN_IE_CAP);
	case_WLAN(IEEE8021X_FAILED);
	case_WLAN(CIPHER_SUITE_REJECTED);
	case_WLAN(DISASSOC_UNSPECIFIED_QOS);
	case_WLAN(DISASSOC_QAP_NO_BANDWIDTH);
	case_WLAN(DISASSOC_LOW_ACK);
	case_WLAN(DISASSOC_QAP_EXCEED_TXOP);
	case_WLAN(QSTA_LEAVE_QBSS);
	case_WLAN(QSTA_NOT_USE);
	case_WLAN(QSTA_REQUIRE_SETUP);
	case_WLAN(QSTA_TIMEOUT);
	case_WLAN(QSTA_CIPHER_NOT_SUPP);
	case_WLAN(MESH_PEER_CANCELED);
	case_WLAN(MESH_MAX_PEERS);
	case_WLAN(MESH_CONFIG);
	case_WLAN(MESH_CLOSE);
	case_WLAN(MESH_MAX_RETRIES);
	case_WLAN(MESH_CONFIRM_TIMEOUT);
	case_WLAN(MESH_INVALID_GTK);
	case_WLAN(MESH_INCONSISTENT_PARAM);
	case_WLAN(MESH_INVALID_SECURITY);
	case_WLAN(MESH_PATH_ERROR);
	case_WLAN(MESH_PATH_NOFORWARD);
	case_WLAN(MESH_PATH_DEST_UNREACHABLE);
	case_WLAN(MAC_EXISTS_IN_MBSS);
	case_WLAN(MESH_CHAN_REGULATORY);
	case_WLAN(MESH_CHAN);
	default: return "<unknown>";
	}
}
J
Johannes Berg 已提交
3089

3090 3091
static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_mgmt *mgmt, size_t len)
3092
{
3093
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3094
	u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
3095

3096
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
3097

3098
	if (len < 24 + 2)
3099
		return;
3100

3101 3102 3103 3104 3105
	if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) {
		ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code);
		return;
	}

3106 3107 3108
	if (ifmgd->associated &&
	    ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) {
		const u8 *bssid = ifmgd->associated->bssid;
3109

3110 3111 3112
		sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n",
			   bssid, reason_code,
			   ieee80211_get_reason_code_string(reason_code));
3113

3114
		ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
3115

3116
		ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false,
3117
					    reason_code, false);
3118 3119
		return;
	}
3120

3121 3122 3123
	if (ifmgd->assoc_data &&
	    ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
		const u8 *bssid = ifmgd->assoc_data->bss->bssid;
3124

3125 3126 3127 3128 3129
		sdata_info(sdata,
			   "deauthenticated from %pM while associating (Reason: %u=%s)\n",
			   bssid, reason_code,
			   ieee80211_get_reason_code_string(reason_code));

3130
		ieee80211_destroy_assoc_data(sdata, false, true);
3131 3132 3133 3134

		cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
		return;
	}
3135 3136 3137
}


3138 3139
static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
				       struct ieee80211_mgmt *mgmt, size_t len)
3140
{
3141
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3142 3143
	u16 reason_code;

3144
	sdata_assert_lock(sdata);
3145

J
Johannes Berg 已提交
3146
	if (len < 24 + 2)
3147
		return;
3148

J
Johannes Berg 已提交
3149
	if (!ifmgd->associated ||
3150
	    !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
3151
		return;
3152 3153 3154

	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);

3155 3156 3157 3158 3159
	if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) {
		ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code);
		return;
	}

3160 3161 3162
	sdata_info(sdata, "disassociated from %pM (Reason: %u=%s)\n",
		   mgmt->sa, reason_code,
		   ieee80211_get_reason_code_string(reason_code));
3163

3164 3165
	ieee80211_set_disassoc(sdata, 0, 0, false, NULL);

3166 3167
	ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code,
				    false);
3168 3169
}

3170 3171 3172 3173
static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
				u8 *supp_rates, unsigned int supp_rates_len,
				u32 *rates, u32 *basic_rates,
				bool *have_higher_than_11mbit,
3174
				int *min_rate, int *min_rate_index,
3175
				int shift)
3176 3177 3178 3179
{
	int i, j;

	for (i = 0; i < supp_rates_len; i++) {
3180
		int rate = supp_rates[i] & 0x7f;
3181 3182
		bool is_basic = !!(supp_rates[i] & 0x80);

3183
		if ((rate * 5 * (1 << shift)) > 110)
3184 3185 3186
			*have_higher_than_11mbit = true;

		/*
3187 3188
		 * Skip HT, VHT, HE and SAE H2E only BSS membership selectors
		 * since they're not rates.
3189
		 *
3190
		 * Note: Even though the membership selector and the basic
3191 3192 3193
		 *	 rate flag share the same bit, they are not exactly
		 *	 the same.
		 */
3194
		if (supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY) ||
3195
		    supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY) ||
3196 3197
		    supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HE_PHY) ||
		    supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E))
3198 3199 3200
			continue;

		for (j = 0; j < sband->n_bitrates; j++) {
3201 3202 3203 3204 3205 3206 3207
			struct ieee80211_rate *br;
			int brate;

			br = &sband->bitrates[j];

			brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
			if (brate == rate) {
3208 3209 3210
				*rates |= BIT(j);
				if (is_basic)
					*basic_rates |= BIT(j);
3211 3212
				if ((rate * 5) < *min_rate) {
					*min_rate = rate * 5;
3213 3214 3215 3216 3217 3218 3219
					*min_rate_index = j;
				}
				break;
			}
		}
	}
}
3220

3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233
static bool ieee80211_twt_req_supported(const struct sta_info *sta,
					const struct ieee802_11_elems *elems)
{
	if (elems->ext_capab_len < 10)
		return false;

	if (!(elems->ext_capab[9] & WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT))
		return false;

	return sta->sta.he_cap.he_cap_elem.mac_cap_info[0] &
		IEEE80211_HE_MAC_CAP0_TWT_RES;
}

3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246
static int ieee80211_recalc_twt_req(struct ieee80211_sub_if_data *sdata,
				    struct sta_info *sta,
				    struct ieee802_11_elems *elems)
{
	bool twt = ieee80211_twt_req_supported(sta, elems);

	if (sdata->vif.bss_conf.twt_requester != twt) {
		sdata->vif.bss_conf.twt_requester = twt;
		return BSS_CHANGED_TWT;
	}
	return 0;
}

3247 3248
static bool ieee80211_twt_bcast_support(struct ieee80211_sub_if_data *sdata,
					struct ieee80211_bss_conf *bss_conf,
3249 3250 3251 3252
					struct ieee80211_supported_band *sband,
					struct sta_info *sta)
{
	const struct ieee80211_sta_he_cap *own_he_cap =
3253 3254
		ieee80211_get_he_iftype_cap(sband,
					    ieee80211_vif_type_p2p(&sdata->vif));
3255 3256 3257 3258 3259 3260 3261 3262 3263

	return bss_conf->he_support &&
		(sta->sta.he_cap.he_cap_elem.mac_cap_info[2] &
			IEEE80211_HE_MAC_CAP2_BCAST_TWT) &&
		own_he_cap &&
		(own_he_cap->he_cap_elem.mac_cap_info[2] &
			IEEE80211_HE_MAC_CAP2_BCAST_TWT);
}

J
Johannes Berg 已提交
3264 3265
static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
				    struct cfg80211_bss *cbss,
3266 3267
				    struct ieee80211_mgmt *mgmt, size_t len,
				    struct ieee802_11_elems *elems)
3268
{
3269
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3270
	struct ieee80211_local *local = sdata->local;
3271
	struct ieee80211_supported_band *sband;
3272
	struct sta_info *sta;
J
Johannes Berg 已提交
3273
	u16 capab_info, aid;
J
Johannes Berg 已提交
3274
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
3275 3276
	const struct cfg80211_bss_ies *bss_ies = NULL;
	struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
3277
	bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
3278
	bool is_s1g = cbss->channel->band == NL80211_BAND_S1GHZ;
J
Johannes Berg 已提交
3279
	u32 changed = 0;
3280
	u8 *pos;
3281
	int err;
3282
	bool ret;
3283

J
Johannes Berg 已提交
3284
	/* AssocResp and ReassocResp have identical structure */
3285

3286
	pos = mgmt->u.assoc_resp.variable;
3287
	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
3288 3289 3290 3291
	if (is_s1g) {
		pos = (u8 *) mgmt->u.s1g_assoc_resp.variable;
		aid = 0; /* TODO */
	}
J
Johannes Berg 已提交
3292
	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
3293 3294 3295 3296 3297
	ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, elems,
			       mgmt->bssid, assoc_data->bss->bssid);

	if (elems->aid_resp)
		aid = le16_to_cpu(elems->aid_resp->aid);
3298

3299 3300 3301 3302 3303
	/*
	 * The 5 MSB of the AID field are reserved
	 * (802.11-2016 9.4.1.8 AID field)
	 */
	aid &= 0x7ff;
3304

3305 3306 3307
	ifmgd->broken_ap = false;

	if (aid == 0 || aid > IEEE80211_MAX_AID) {
J
Johannes Berg 已提交
3308 3309
		sdata_info(sdata, "invalid AID value %d (out of range), turn off PS\n",
			   aid);
3310 3311 3312 3313
		aid = 0;
		ifmgd->broken_ap = true;
	}

3314
	if (!is_s1g && !elems->supp_rates) {
J
Johannes Berg 已提交
3315
		sdata_info(sdata, "no SuppRates element in AssocResp\n");
J
Johannes Berg 已提交
3316
		return false;
3317 3318
	}

3319
	sdata->vif.bss_conf.aid = aid;
3320
	ifmgd->tdls_chan_switch_prohibited =
3321 3322
		elems->ext_capab && elems->ext_capab_len >= 5 &&
		(elems->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
3323

3324 3325 3326 3327 3328 3329 3330
	/*
	 * Some APs are erroneously not including some information in their
	 * (re)association response frames. Try to recover by using the data
	 * from the beacon or probe response. This seems to afflict mobile
	 * 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
	 * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
	 */
3331 3332 3333 3334 3335 3336
	if (!is_6ghz &&
	    ((assoc_data->wmm && !elems->wmm_param) ||
	     (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
	      (!elems->ht_cap_elem || !elems->ht_operation)) ||
	     (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
	      (!elems->vht_cap_elem || !elems->vht_operation)))) {
3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349
		const struct cfg80211_bss_ies *ies;
		struct ieee802_11_elems bss_elems;

		rcu_read_lock();
		ies = rcu_dereference(cbss->ies);
		if (ies)
			bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
					  GFP_ATOMIC);
		rcu_read_unlock();
		if (!bss_ies)
			return false;

		ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
3350 3351 3352
				       false, &bss_elems,
				       mgmt->bssid,
				       assoc_data->bss->bssid);
3353
		if (assoc_data->wmm &&
3354 3355
		    !elems->wmm_param && bss_elems.wmm_param) {
			elems->wmm_param = bss_elems.wmm_param;
3356 3357 3358 3359 3360 3361 3362 3363
			sdata_info(sdata,
				   "AP bug: WMM param missing from AssocResp\n");
		}

		/*
		 * Also check if we requested HT/VHT, otherwise the AP doesn't
		 * have to include the IEs in the (re)association response.
		 */
3364
		if (!elems->ht_cap_elem && bss_elems.ht_cap_elem &&
3365
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
3366
			elems->ht_cap_elem = bss_elems.ht_cap_elem;
3367 3368 3369
			sdata_info(sdata,
				   "AP bug: HT capability missing from AssocResp\n");
		}
3370
		if (!elems->ht_operation && bss_elems.ht_operation &&
3371
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
3372
			elems->ht_operation = bss_elems.ht_operation;
3373 3374 3375
			sdata_info(sdata,
				   "AP bug: HT operation missing from AssocResp\n");
		}
3376
		if (!elems->vht_cap_elem && bss_elems.vht_cap_elem &&
3377
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
3378
			elems->vht_cap_elem = bss_elems.vht_cap_elem;
3379 3380 3381
			sdata_info(sdata,
				   "AP bug: VHT capa missing from AssocResp\n");
		}
3382
		if (!elems->vht_operation && bss_elems.vht_operation &&
3383
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
3384
			elems->vht_operation = bss_elems.vht_operation;
3385 3386 3387 3388 3389
			sdata_info(sdata,
				   "AP bug: VHT operation missing from AssocResp\n");
		}
	}

3390 3391 3392 3393
	/*
	 * We previously checked these in the beacon/probe response, so
	 * they should be present here. This is just a safety net.
	 */
3394
	if (!is_6ghz && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
3395
	    (!elems->wmm_param || !elems->ht_cap_elem || !elems->ht_operation)) {
3396
		sdata_info(sdata,
3397 3398 3399
			   "HT AP is missing WMM params or HT capability/operation\n");
		ret = false;
		goto out;
3400 3401
	}

3402
	if (!is_6ghz && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
3403
	    (!elems->vht_cap_elem || !elems->vht_operation)) {
3404
		sdata_info(sdata,
3405 3406 3407
			   "VHT AP is missing VHT capability/operation\n");
		ret = false;
		goto out;
3408 3409
	}

3410 3411 3412 3413 3414 3415 3416 3417
	if (is_6ghz && !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) &&
	    !elems->he_6ghz_capa) {
		sdata_info(sdata,
			   "HE 6 GHz AP is missing HE 6 GHz band capability\n");
		ret = false;
		goto out;
	}

3418 3419 3420 3421 3422
	mutex_lock(&sdata->local->sta_mtx);
	/*
	 * station info was already allocated and inserted before
	 * the association and should be available to us
	 */
3423
	sta = sta_info_get(sdata, cbss->bssid);
3424 3425
	if (WARN_ON(!sta)) {
		mutex_unlock(&sdata->local->sta_mtx);
3426 3427
		ret = false;
		goto out;
3428
	}
3429

3430 3431 3432 3433 3434 3435
	sband = ieee80211_get_sband(sdata);
	if (!sband) {
		mutex_unlock(&sdata->local->sta_mtx);
		ret = false;
		goto out;
	}
3436

L
Luca Coelho 已提交
3437
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE) &&
3438
	    (!elems->he_cap || !elems->he_operation)) {
L
Luca Coelho 已提交
3439 3440 3441 3442 3443 3444 3445
		mutex_unlock(&sdata->local->sta_mtx);
		sdata_info(sdata,
			   "HE AP is missing HE capability/operation\n");
		ret = false;
		goto out;
	}

3446
	/* Set up internal HT/VHT capabilities */
3447
	if (elems->ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
B
Ben Greear 已提交
3448
		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
3449
						  elems->ht_cap_elem, sta);
3450

3451
	if (elems->vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
M
Mahesh Palivela 已提交
3452
		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
3453
						    elems->vht_cap_elem, sta);
M
Mahesh Palivela 已提交
3454

3455 3456
	if (elems->he_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) &&
	    elems->he_cap) {
L
Luca Coelho 已提交
3457
		ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
3458 3459
						  elems->he_cap,
						  elems->he_cap_len,
3460
						  elems->he_6ghz_capa,
L
Luca Coelho 已提交
3461 3462 3463
						  sta);

		bss_conf->he_support = sta->sta.he_cap.has_he;
3464 3465 3466 3467 3468 3469 3470 3471
		if (elems->rsnx && elems->rsnx_len &&
		    (elems->rsnx[0] & WLAN_RSNX_CAPA_PROTECTED_TWT) &&
		    wiphy_ext_feature_isset(local->hw.wiphy,
					    NL80211_EXT_FEATURE_PROTECTED_TWT))
			bss_conf->twt_protected = true;
		else
			bss_conf->twt_protected = false;

3472
		changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
L
Luca Coelho 已提交
3473 3474
	} else {
		bss_conf->he_support = false;
3475
		bss_conf->twt_requester = false;
3476
		bss_conf->twt_protected = false;
L
Luca Coelho 已提交
3477 3478
	}

3479
	bss_conf->twt_broadcast =
3480
		ieee80211_twt_bcast_support(sdata, bss_conf, sband, sta);
3481

L
Luca Coelho 已提交
3482
	if (bss_conf->he_support) {
3483
		bss_conf->he_bss_color.color =
3484
			le32_get_bits(elems->he_operation->he_oper_params,
3485
				      IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
3486 3487 3488
		bss_conf->he_bss_color.partial =
			le32_get_bits(elems->he_operation->he_oper_params,
				      IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR);
3489 3490 3491
		bss_conf->he_bss_color.enabled =
			!le32_get_bits(elems->he_operation->he_oper_params,
				       IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED);
3492

3493
		if (bss_conf->he_bss_color.enabled)
3494
			changed |= BSS_CHANGED_HE_BSS_COLOR;
L
Luca Coelho 已提交
3495 3496

		bss_conf->htc_trig_based_pkt_ext =
3497
			le32_get_bits(elems->he_operation->he_oper_params,
3498
			      IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK);
L
Luca Coelho 已提交
3499
		bss_conf->frame_time_rts_th =
3500
			le32_get_bits(elems->he_operation->he_oper_params,
3501
			      IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
L
Luca Coelho 已提交
3502

3503 3504 3505
		bss_conf->uora_exists = !!elems->uora_element;
		if (elems->uora_element)
			bss_conf->uora_ocw_range = elems->uora_element[0];
L
Luca Coelho 已提交
3506

3507 3508
		ieee80211_he_op_ie_to_bss_conf(&sdata->vif, elems->he_operation);
		ieee80211_he_spr_ie_to_bss_conf(&sdata->vif, elems->he_spr);
L
Luca Coelho 已提交
3509 3510 3511
		/* TODO: OPEN: what happens if BSS color disable is set? */
	}

S
Sara Sharon 已提交
3512 3513 3514 3515 3516 3517 3518 3519
	if (cbss->transmitted_bss) {
		bss_conf->nontransmitted = true;
		ether_addr_copy(bss_conf->transmitter_bssid,
				cbss->transmitted_bss->bssid);
		bss_conf->bssid_indicator = cbss->max_bssid_indicator;
		bss_conf->bssid_index = cbss->bssid_index;
	}

3520 3521 3522 3523 3524 3525
	/*
	 * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data
	 * in their association response, so ignore that data for our own
	 * configuration. If it changed since the last beacon, we'll get the
	 * next beacon and update then.
	 */
3526

3527 3528 3529 3530 3531
	/*
	 * If an operating mode notification IE is present, override the
	 * NSS calculation (that would be done in rate_control_rate_init())
	 * and use the # of streams from that element.
	 */
3532 3533
	if (elems->opmode_notif &&
	    !(*elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)) {
3534 3535
		u8 nss;

3536
		nss = *elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK;
3537 3538 3539 3540 3541
		nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
		nss += 1;
		sta->sta.rx_nss = nss;
	}

3542
	rate_control_rate_init(sta);
3543

3544
	if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) {
J
Johannes Berg 已提交
3545
		set_sta_flag(sta, WLAN_STA_MFP);
3546 3547 3548 3549
		sta->sta.mfp = true;
	} else {
		sta->sta.mfp = false;
	}
3550

3551 3552
	sta->sta.wme = (elems->wmm_param || elems->s1g_capab) &&
		       local->hw.queues >= IEEE80211_NUM_ACS;
3553

3554
	err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
3555 3556 3557
	if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
		err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
	if (err) {
J
Johannes Berg 已提交
3558 3559 3560
		sdata_info(sdata,
			   "failed to move station %pM to desired state\n",
			   sta->sta.addr);
3561 3562
		WARN_ON(__sta_info_destroy(sta));
		mutex_unlock(&sdata->local->sta_mtx);
3563 3564
		ret = false;
		goto out;
3565 3566
	}

3567 3568 3569
	if (sdata->wdev.use_4addr)
		drv_sta_set_4addr(local, sdata, &sta->sta, true);

3570
	mutex_unlock(&sdata->local->sta_mtx);
3571

3572 3573 3574 3575 3576 3577 3578
	/*
	 * Always handle WMM once after association regardless
	 * of the first value the AP uses. Setting -1 here has
	 * that effect because the AP values is an unsigned
	 * 4-bit value.
	 */
	ifmgd->wmm_last_param_set = -1;
3579
	ifmgd->mu_edca_last_param_set = -1;
3580

3581
	if (ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
3582
		ieee80211_set_wmm_default(sdata, false, false);
3583 3584 3585
	} else if (!ieee80211_sta_wmm_params(local, sdata, elems->wmm_param,
					     elems->wmm_param_len,
					     elems->mu_edca_param_set)) {
3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596
		/* still enable QoS since we might have HT/VHT */
		ieee80211_set_wmm_default(sdata, false, true);
		/* set the disable-WMM flag in this case to disable
		 * tracking WMM parameter changes in the beacon if
		 * the parameters weren't actually valid. Doing so
		 * avoids changing parameters very strangely when
		 * the AP is going back and forth between valid and
		 * invalid parameters.
		 */
		ifmgd->flags |= IEEE80211_STA_DISABLE_WMM;
	}
3597
	changed |= BSS_CHANGED_QOS;
3598

3599
	if (elems->max_idle_period_ie) {
3600
		bss_conf->max_idle_period =
3601
			le16_to_cpu(elems->max_idle_period_ie->max_idle_period);
3602
		bss_conf->protected_keep_alive =
3603
			!!(elems->max_idle_period_ie->idle_options &
3604 3605 3606 3607 3608 3609 3610
			   WLAN_IDLE_OPTIONS_PROTECTED_KEEP_ALIVE);
		changed |= BSS_CHANGED_KEEP_ALIVE;
	} else {
		bss_conf->max_idle_period = 0;
		bss_conf->protected_keep_alive = false;
	}

3611
	/* set assoc capability (AID was already set earlier),
J
Johannes Berg 已提交
3612 3613
	 * ieee80211_set_associated() will tell the driver */
	bss_conf->assoc_capability = capab_info;
3614
	ieee80211_set_associated(sdata, cbss, changed);
3615

3616 3617 3618 3619 3620 3621 3622
	/*
	 * If we're using 4-addr mode, let the AP know that we're
	 * doing so, so that it can create the STA VLAN on its side
	 */
	if (ifmgd->use_4addr)
		ieee80211_send_4addr_nullfunc(local, sdata);

3623
	/*
J
Johannes Berg 已提交
3624 3625
	 * Start timer to probe the connection to the AP now.
	 * Also start the timer that will detect beacon loss.
3626
	 */
3627
	ieee80211_sta_reset_beacon_monitor(sdata);
3628
	ieee80211_sta_reset_conn_monitor(sdata);
3629

3630 3631 3632 3633
	ret = true;
 out:
	kfree(bss_ies);
	return ret;
3634 3635
}

3636 3637 3638
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
					 struct ieee80211_mgmt *mgmt,
					 size_t len)
J
Johannes Berg 已提交
3639 3640 3641 3642 3643
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
	u16 capab_info, status_code, aid;
	struct ieee802_11_elems elems;
3644
	int ac, uapsd_queues = -1;
J
Johannes Berg 已提交
3645 3646
	u8 *pos;
	bool reassoc;
3647
	struct cfg80211_bss *cbss;
3648 3649 3650 3651
	struct ieee80211_event event = {
		.type = MLME_EVENT,
		.u.mlme.data = ASSOC_EVENT,
	};
3652
	struct ieee80211_prep_tx_info info = {};
J
Johannes Berg 已提交
3653

3654
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
3655 3656

	if (!assoc_data)
3657
		return;
3658

3659
	if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid))
3660
		return;
J
Johannes Berg 已提交
3661

3662 3663
	cbss = assoc_data->bss;

J
Johannes Berg 已提交
3664 3665 3666 3667 3668 3669
	/*
	 * AssocResp and ReassocResp have identical structure, so process both
	 * of them in this function.
	 */

	if (len < 24 + 6)
3670
		return;
J
Johannes Berg 已提交
3671

3672
	reassoc = ieee80211_is_reassoc_resp(mgmt->frame_control);
J
Johannes Berg 已提交
3673 3674
	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
3675
	pos = mgmt->u.assoc_resp.variable;
J
Johannes Berg 已提交
3676
	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
3677 3678 3679 3680
	if (cbss->channel->band == NL80211_BAND_S1GHZ) {
		pos = (u8 *) mgmt->u.s1g_assoc_resp.variable;
		aid = 0; /* TODO */
	}
J
Johannes Berg 已提交
3681

3682 3683 3684 3685 3686 3687 3688 3689 3690
	/*
	 * Note: this may not be perfect, AP might misbehave - if
	 * anyone needs to rely on perfect complete notification
	 * with the exact right subtype, then we need to track what
	 * we actually transmitted.
	 */
	info.subtype = reassoc ? IEEE80211_STYPE_REASSOC_REQ :
				 IEEE80211_STYPE_ASSOC_REQ;

J
Johannes Berg 已提交
3691 3692 3693 3694
	sdata_info(sdata,
		   "RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n",
		   reassoc ? "Rea" : "A", mgmt->sa,
		   capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
J
Johannes Berg 已提交
3695

3696 3697 3698 3699
	if (assoc_data->fils_kek_len &&
	    fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0)
		return;

3700 3701
	ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
			       mgmt->bssid, assoc_data->bss->bssid);
J
Johannes Berg 已提交
3702 3703

	if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
3704 3705
	    elems.timeout_int &&
	    elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
J
Johannes Berg 已提交
3706
		u32 tu, ms;
3707
		tu = le32_to_cpu(elems.timeout_int->value);
J
Johannes Berg 已提交
3708
		ms = tu * 1024 / 1000;
J
Johannes Berg 已提交
3709 3710 3711
		sdata_info(sdata,
			   "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
			   mgmt->sa, tu, ms);
J
Johannes Berg 已提交
3712
		assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
3713
		assoc_data->timeout_started = true;
J
Johannes Berg 已提交
3714
		if (ms > IEEE80211_ASSOC_TIMEOUT)
3715
			run_again(sdata, assoc_data->timeout);
3716
		goto notify_driver;
J
Johannes Berg 已提交
3717 3718 3719
	}

	if (status_code != WLAN_STATUS_SUCCESS) {
J
Johannes Berg 已提交
3720 3721
		sdata_info(sdata, "%pM denied association (code=%d)\n",
			   mgmt->sa, status_code);
3722
		ieee80211_destroy_assoc_data(sdata, false, false);
3723 3724 3725
		event.u.mlme.status = MLME_DENIED;
		event.u.mlme.reason = status_code;
		drv_event_callback(sdata->local, sdata, &event);
J
Johannes Berg 已提交
3726
	} else {
3727
		if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, &elems)) {
J
Johannes Berg 已提交
3728
			/* oops -- internal error -- send timeout for now */
3729
			ieee80211_destroy_assoc_data(sdata, false, false);
3730
			cfg80211_assoc_timeout(sdata->dev, cbss);
3731
			goto notify_driver;
J
Johannes Berg 已提交
3732
		}
3733 3734
		event.u.mlme.status = MLME_SUCCESS;
		drv_event_callback(sdata->local, sdata, &event);
3735
		sdata_info(sdata, "associated\n");
3736 3737 3738 3739 3740 3741

		/*
		 * destroy assoc_data afterwards, as otherwise an idle
		 * recalc after assoc_data is NULL but before associated
		 * is set can cause the interface to go idle
		 */
3742
		ieee80211_destroy_assoc_data(sdata, true, false);
3743 3744 3745 3746 3747

		/* get uapsd queues configuration */
		uapsd_queues = 0;
		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
			if (sdata->tx_conf[ac].uapsd)
3748
				uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
3749 3750

		info.success = 1;
J
Johannes Berg 已提交
3751 3752
	}

3753
	cfg80211_rx_assoc_resp(sdata->dev, cbss, (u8 *)mgmt, len, uapsd_queues,
3754
			       ifmgd->assoc_req_ies, ifmgd->assoc_req_ies_len);
3755 3756
notify_driver:
	drv_mgd_complete_tx(sdata->local, sdata, &info);
J
Johannes Berg 已提交
3757
}
J
Johannes Berg 已提交
3758

3759
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
3760
				  struct ieee80211_mgmt *mgmt, size_t len,
3761
				  struct ieee80211_rx_status *rx_status)
3762 3763
{
	struct ieee80211_local *local = sdata->local;
3764
	struct ieee80211_bss *bss;
3765
	struct ieee80211_channel *channel;
3766

3767
	sdata_assert_lock(sdata);
3768

3769 3770
	channel = ieee80211_get_channel_khz(local->hw.wiphy,
					ieee80211_rx_status_to_khz(rx_status));
3771
	if (!channel)
3772 3773
		return;

3774
	bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, channel);
3775 3776
	if (bss) {
		sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
3777
		ieee80211_rx_bss_put(local, bss);
3778
	}
3779 3780 3781
}


3782
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
3783
					 struct sk_buff *skb)
3784
{
J
Johannes Berg 已提交
3785
	struct ieee80211_mgmt *mgmt = (void *)skb->data;
3786
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
3787
	struct ieee80211_rx_status *rx_status = (void *) skb->cb;
3788
	struct ieee80211_channel *channel;
J
Johannes Berg 已提交
3789
	size_t baselen, len = skb->len;
3790

3791 3792
	ifmgd = &sdata->u.mgd;

3793
	sdata_assert_lock(sdata);
3794

3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809
	/*
	 * According to Draft P802.11ax D6.0 clause 26.17.2.3.2:
	 * "If a 6 GHz AP receives a Probe Request frame  and responds with
	 * a Probe Response frame [..], the Address 1 field of the Probe
	 * Response frame shall be set to the broadcast address [..]"
	 * So, on 6GHz band we should also accept broadcast responses.
	 */
	channel = ieee80211_get_channel(sdata->local->hw.wiphy,
					rx_status->freq);
	if (!channel)
		return;

	if (!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
	    (channel->band != NL80211_BAND_6GHZ ||
	     !is_broadcast_ether_addr(mgmt->da)))
3810 3811
		return; /* ignore ProbeResp to foreign address */

3812 3813 3814 3815
	baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
	if (baselen > len)
		return;

3816
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
3817

3818
	if (ifmgd->associated &&
3819
	    ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
3820
		ieee80211_reset_ap_probe(sdata);
3821 3822
}

3823 3824 3825
/*
 * This is the canonical list of information elements we care about,
 * the filter code also gives us all changes to the Microsoft OUI
3826 3827 3828
 * (00:50:F2) vendor IE which is used for WMM which we need to track,
 * as well as the DTPC IE (part of the Cisco OUI) used for signaling
 * changes to requested client power.
3829 3830 3831 3832 3833 3834 3835 3836 3837 3838
 *
 * We implement beacon filtering in software since that means we can
 * avoid processing the frame here and in cfg80211, and userspace
 * will not be able to tell whether the hardware supports it or not.
 *
 * XXX: This list needs to be dynamic -- userspace needs to be able to
 *	add items it requires. It also needs to be able to tell us to
 *	look out for other vendor IEs.
 */
static const u64 care_about_ies =
3839 3840 3841 3842 3843
	(1ULL << WLAN_EID_COUNTRY) |
	(1ULL << WLAN_EID_ERP_INFO) |
	(1ULL << WLAN_EID_CHANNEL_SWITCH) |
	(1ULL << WLAN_EID_PWR_CONSTRAINT) |
	(1ULL << WLAN_EID_HT_CAPABILITY) |
3844 3845
	(1ULL << WLAN_EID_HT_OPERATION) |
	(1ULL << WLAN_EID_EXT_CHANSWITCH_ANN);
3846

3847 3848 3849 3850 3851
static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata,
					struct ieee80211_if_managed *ifmgd,
					struct ieee80211_bss_conf *bss_conf,
					struct ieee80211_local *local,
					struct ieee80211_rx_status *rx_status)
3852
{
3853
	/* Track average RSSI from the Beacon frames of the current AP */
3854

3855 3856
	if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
		ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
3857
		ewma_beacon_signal_init(&ifmgd->ave_beacon_signal);
3858
		ifmgd->last_cqm_event_signal = 0;
3859
		ifmgd->count_beacon_signal = 1;
3860
		ifmgd->last_ave_beacon_signal = 0;
3861
	} else {
3862
		ifmgd->count_beacon_signal++;
3863
	}
3864

3865 3866
	ewma_beacon_signal_add(&ifmgd->ave_beacon_signal, -rx_status->signal);

3867 3868
	if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
3869
		int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
3870
		int last_sig = ifmgd->last_ave_beacon_signal;
3871 3872 3873
		struct ieee80211_event event = {
			.type = RSSI_EVENT,
		};
3874 3875 3876 3877 3878 3879 3880 3881

		/*
		 * if signal crosses either of the boundaries, invoke callback
		 * with appropriate parameters
		 */
		if (sig > ifmgd->rssi_max_thold &&
		    (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) {
			ifmgd->last_ave_beacon_signal = sig;
3882 3883
			event.u.rssi.data = RSSI_EVENT_HIGH;
			drv_event_callback(local, sdata, &event);
3884 3885 3886 3887
		} else if (sig < ifmgd->rssi_min_thold &&
			   (last_sig >= ifmgd->rssi_max_thold ||
			   last_sig == 0)) {
			ifmgd->last_ave_beacon_signal = sig;
3888 3889
			event.u.rssi.data = RSSI_EVENT_LOW;
			drv_event_callback(local, sdata, &event);
3890 3891 3892
		}
	}

3893
	if (bss_conf->cqm_rssi_thold &&
3894
	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
3895
	    !(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) {
3896
		int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
3897 3898 3899
		int last_event = ifmgd->last_cqm_event_signal;
		int thold = bss_conf->cqm_rssi_thold;
		int hyst = bss_conf->cqm_rssi_hyst;
3900

3901 3902 3903 3904 3905 3906
		if (sig < thold &&
		    (last_event == 0 || sig < last_event - hyst)) {
			ifmgd->last_cqm_event_signal = sig;
			ieee80211_cqm_rssi_notify(
				&sdata->vif,
				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
3907
				sig, GFP_KERNEL);
3908 3909 3910 3911 3912 3913
		} else if (sig > thold &&
			   (last_event == 0 || sig > last_event + hyst)) {
			ifmgd->last_cqm_event_signal = sig;
			ieee80211_cqm_rssi_notify(
				&sdata->vif,
				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
3914
				sig, GFP_KERNEL);
3915 3916 3917
		}
	}

3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940
	if (bss_conf->cqm_rssi_low &&
	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
		int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
		int last_event = ifmgd->last_cqm_event_signal;
		int low = bss_conf->cqm_rssi_low;
		int high = bss_conf->cqm_rssi_high;

		if (sig < low &&
		    (last_event == 0 || last_event >= low)) {
			ifmgd->last_cqm_event_signal = sig;
			ieee80211_cqm_rssi_notify(
				&sdata->vif,
				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
				sig, GFP_KERNEL);
		} else if (sig > high &&
			   (last_event == 0 || last_event <= high)) {
			ifmgd->last_cqm_event_signal = sig;
			ieee80211_cqm_rssi_notify(
				&sdata->vif,
				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
				sig, GFP_KERNEL);
		}
	}
3941 3942
}

S
Sara Sharon 已提交
3943 3944 3945 3946 3947 3948 3949 3950 3951 3952
static bool ieee80211_rx_our_beacon(const u8 *tx_bssid,
				    struct cfg80211_bss *bss)
{
	if (ether_addr_equal(tx_bssid, bss->bssid))
		return true;
	if (!bss->transmitted_bss)
		return false;
	return ether_addr_equal(tx_bssid, bss->transmitted_bss->bssid);
}

3953
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3954
				     struct ieee80211_hdr *hdr, size_t len,
3955 3956 3957 3958
				     struct ieee80211_rx_status *rx_status)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
3959
	struct ieee80211_mgmt *mgmt = (void *) hdr;
3960 3961 3962 3963 3964 3965 3966 3967 3968
	size_t baselen;
	struct ieee802_11_elems elems;
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_channel *chan;
	struct sta_info *sta;
	u32 changed = 0;
	bool erp_valid;
	u8 erp_value = 0;
3969 3970
	u32 ncrc = 0;
	u8 *bssid, *variable = mgmt->u.beacon.variable;
3971 3972 3973 3974 3975
	u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];

	sdata_assert_lock(sdata);

	/* Process beacon from the current BSS */
3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986
	bssid = ieee80211_get_bssid(hdr, len, sdata->vif.type);
	if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
		struct ieee80211_ext *ext = (void *) mgmt;

		if (ieee80211_is_s1g_short_beacon(ext->frame_control))
			variable = ext->u.s1g_short_beacon.variable;
		else
			variable = ext->u.s1g_beacon.variable;
	}

	baselen = (u8 *) variable - (u8 *) mgmt;
3987 3988 3989 3990 3991 3992 3993 3994 3995 3996
	if (baselen > len)
		return;

	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
	if (!chanctx_conf) {
		rcu_read_unlock();
		return;
	}

3997 3998
	if (ieee80211_rx_status_to_khz(rx_status) !=
	    ieee80211_channel_to_khz(chanctx_conf->def.chan)) {
3999 4000 4001 4002 4003 4004 4005
		rcu_read_unlock();
		return;
	}
	chan = chanctx_conf->def.chan;
	rcu_read_unlock();

	if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
4006 4007
	    ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->bss)) {
		ieee802_11_parse_elems(variable,
4008
				       len - baselen, false, &elems,
4009
				       bssid,
4010
				       ifmgd->assoc_data->bss->bssid);
4011

4012
		ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
S
Sara Sharon 已提交
4013 4014 4015

		if (elems.dtim_period)
			ifmgd->dtim_period = elems.dtim_period;
4016 4017 4018 4019 4020 4021 4022
		ifmgd->have_beacon = true;
		ifmgd->assoc_data->need_beacon = false;
		if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
			sdata->vif.bss_conf.sync_tsf =
				le64_to_cpu(mgmt->u.beacon.timestamp);
			sdata->vif.bss_conf.sync_device_ts =
				rx_status->device_timestamp;
S
Sara Sharon 已提交
4023
			sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
4024
		}
S
Sara Sharon 已提交
4025 4026 4027 4028

		if (elems.mbssid_config_ie)
			bss_conf->profile_periodicity =
				elems.mbssid_config_ie->profile_periodicity;
4029 4030
		else
			bss_conf->profile_periodicity = 0;
S
Sara Sharon 已提交
4031 4032 4033 4034

		if (elems.ext_capab_len >= 11 &&
		    (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
			bss_conf->ema_ap = true;
4035 4036
		else
			bss_conf->ema_ap = false;
S
Sara Sharon 已提交
4037

4038 4039 4040 4041 4042 4043 4044 4045
		/* continue assoc process */
		ifmgd->assoc_data->timeout = jiffies;
		ifmgd->assoc_data->timeout_started = true;
		run_again(sdata, ifmgd->assoc_data->timeout);
		return;
	}

	if (!ifmgd->associated ||
4046
	    !ieee80211_rx_our_beacon(bssid,  ifmgd->associated))
4047 4048 4049 4050 4051 4052
		return;
	bssid = ifmgd->associated->bssid;

	if (!(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL))
		ieee80211_handle_beacon_sig(sdata, ifmgd, bss_conf,
					    local, rx_status);
4053

4054
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
J
Johannes Berg 已提交
4055
		mlme_dbg_ratelimited(sdata,
4056
				     "cancelling AP probe due to a received beacon\n");
4057
		ieee80211_reset_ap_probe(sdata);
4058 4059
	}

J
Johannes Berg 已提交
4060 4061 4062 4063
	/*
	 * Push the beacon loss detection into the future since
	 * we are processing a beacon from the AP just now.
	 */
4064
	ieee80211_sta_reset_beacon_monitor(sdata);
J
Johannes Berg 已提交
4065

4066 4067 4068 4069 4070 4071 4072 4073
	/* TODO: CRC urrently not calculated on S1G Beacon Compatibility
	 * element (which carries the beacon interval). Don't forget to add a
	 * bit to care_about_ies[] above if mac80211 is interested in a
	 * changing S1G element.
	 */
	if (!ieee80211_is_s1g_beacon(hdr->frame_control))
		ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
	ncrc = ieee802_11_parse_elems_crc(variable,
4074
					  len - baselen, false, &elems,
4075 4076
					  care_about_ies, ncrc,
					  mgmt->bssid, bssid);
4077

4078
	if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
4079
	    ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) {
4080 4081 4082 4083 4084
		if (local->hw.conf.dynamic_ps_timeout > 0) {
			if (local->hw.conf.flags & IEEE80211_CONF_PS) {
				local->hw.conf.flags &= ~IEEE80211_CONF_PS;
				ieee80211_hw_config(local,
						    IEEE80211_CONF_CHANGE_PS);
4085
			}
4086
			ieee80211_send_nullfunc(local, sdata, false);
4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098
		} else if (!local->pspolling && sdata->u.mgd.powersave) {
			local->pspolling = true;

			/*
			 * Here is assumed that the driver will be
			 * able to send ps-poll frame and receive a
			 * response even though power save mode is
			 * enabled, but some drivers might require
			 * to disable power save here. This needs
			 * to be investigated.
			 */
			ieee80211_send_pspoll(local, sdata);
4099 4100
		}
	}
J
Johannes Berg 已提交
4101

4102 4103
	if (sdata->vif.p2p ||
	    sdata->vif.driver_flags & IEEE80211_VIF_GET_NOA_UPDATE) {
J
Janusz Dziedzic 已提交
4104
		struct ieee80211_p2p_noa_attr noa = {};
4105 4106
		int ret;

4107
		ret = cfg80211_get_p2p_attr(variable,
4108 4109
					    len - baselen,
					    IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
4110
					    (u8 *) &noa, sizeof(noa));
J
Janusz Dziedzic 已提交
4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126
		if (ret >= 2) {
			if (sdata->u.mgd.p2p_noa_index != noa.index) {
				/* valid noa_attr and index changed */
				sdata->u.mgd.p2p_noa_index = noa.index;
				memcpy(&bss_conf->p2p_noa_attr, &noa, sizeof(noa));
				changed |= BSS_CHANGED_P2P_PS;
				/*
				 * make sure we update all information, the CRC
				 * mechanism doesn't look at P2P attributes.
				 */
				ifmgd->beacon_crc_valid = false;
			}
		} else if (sdata->u.mgd.p2p_noa_index != -1) {
			/* noa_attr not found and we had valid noa_attr before */
			sdata->u.mgd.p2p_noa_index = -1;
			memset(&bss_conf->p2p_noa_attr, 0, sizeof(bss_conf->p2p_noa_attr));
4127 4128 4129 4130 4131
			changed |= BSS_CHANGED_P2P_PS;
			ifmgd->beacon_crc_valid = false;
		}
	}

4132 4133 4134
	if (ifmgd->csa_waiting_bcn)
		ieee80211_chswitch_post_beacon(sdata);

4135 4136 4137 4138 4139 4140 4141 4142
	/*
	 * Update beacon timing and dtim count on every beacon appearance. This
	 * will allow the driver to use the most updated values. Do it before
	 * comparing this one with last received beacon.
	 * IMPORTANT: These parameters would possibly be out of sync by the time
	 * the driver will use them. The synchronized view is currently
	 * guaranteed only in certain callbacks.
	 */
4143 4144
	if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) &&
	    !ieee80211_is_s1g_beacon(hdr->frame_control)) {
4145 4146 4147 4148
		sdata->vif.bss_conf.sync_tsf =
			le64_to_cpu(mgmt->u.beacon.timestamp);
		sdata->vif.bss_conf.sync_device_ts =
			rx_status->device_timestamp;
S
Sara Sharon 已提交
4149
		sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
4150 4151
	}

4152 4153
	if ((ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) ||
	    ieee80211_is_s1g_short_beacon(mgmt->frame_control))
4154
		return;
4155
	ifmgd->beacon_crc = ncrc;
4156
	ifmgd->beacon_crc_valid = true;
4157

4158
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
4159

4160
	ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
4161
					 rx_status->device_timestamp,
4162 4163
					 &elems, true);

4164 4165
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
	    ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
L
Luca Coelho 已提交
4166 4167
				     elems.wmm_param_len,
				     elems.mu_edca_param_set))
4168 4169
		changed |= BSS_CHANGED_QOS;

4170 4171
	/*
	 * If we haven't had a beacon before, tell the driver about the
4172
	 * DTIM period (and beacon timing if desired) now.
4173
	 */
4174
	if (!ifmgd->have_beacon) {
4175
		/* a few bogus AP send dtim_period = 0 or no TIM IE */
S
Sara Sharon 已提交
4176
		bss_conf->dtim_period = elems.dtim_period ?: 1;
4177

4178 4179
		changed |= BSS_CHANGED_BEACON_INFO;
		ifmgd->have_beacon = true;
4180 4181

		mutex_lock(&local->iflist_mtx);
J
Johannes Berg 已提交
4182
		ieee80211_recalc_ps(local);
4183 4184
		mutex_unlock(&local->iflist_mtx);

4185
		ieee80211_recalc_ps_vif(sdata);
4186 4187
	}

4188
	if (elems.erp_info) {
J
Johannes Berg 已提交
4189 4190 4191 4192
		erp_valid = true;
		erp_value = elems.erp_info[0];
	} else {
		erp_valid = false;
4193
	}
4194 4195 4196 4197 4198

	if (!ieee80211_is_s1g_beacon(hdr->frame_control))
		changed |= ieee80211_handle_bss_capability(sdata,
				le16_to_cpu(mgmt->u.beacon.capab_info),
				erp_valid, erp_value);
4199

4200
	mutex_lock(&local->sta_mtx);
4201 4202
	sta = sta_info_get(sdata, bssid);

4203 4204
	changed |= ieee80211_recalc_twt_req(sdata, sta, &elems);

4205 4206
	if (ieee80211_config_bw(sdata, sta, elems.ht_cap_elem,
				elems.vht_cap_elem, elems.ht_operation,
L
Luca Coelho 已提交
4207
				elems.vht_operation, elems.he_operation,
4208
				elems.s1g_oper, bssid, &changed)) {
4209
		mutex_unlock(&local->sta_mtx);
4210 4211 4212
		sdata_info(sdata,
			   "failed to follow AP %pM bandwidth change, disconnect\n",
			   bssid);
4213 4214 4215
		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       WLAN_REASON_DEAUTH_LEAVING,
				       true, deauth_buf);
4216 4217
		ieee80211_report_disconnect(sdata, deauth_buf,
					    sizeof(deauth_buf), true,
4218 4219
					    WLAN_REASON_DEAUTH_LEAVING,
					    false);
4220
		return;
4221
	}
4222 4223 4224

	if (sta && elems.opmode_notif)
		ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
4225
					    rx_status->band);
4226
	mutex_unlock(&local->sta_mtx);
4227

4228 4229 4230
	changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
					       elems.country_elem,
					       elems.country_elem_len,
4231 4232
					       elems.pwr_constr_elem,
					       elems.cisco_dtpc_elem);
4233

4234
	ieee80211_bss_info_change_notify(sdata, changed);
4235 4236
}

4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256
void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
				 struct sk_buff *skb)
{
	struct ieee80211_rx_status *rx_status;
	struct ieee80211_hdr *hdr;
	u16 fc;

	rx_status = (struct ieee80211_rx_status *) skb->cb;
	hdr = (struct ieee80211_hdr *) skb->data;
	fc = le16_to_cpu(hdr->frame_control);

	sdata_lock(sdata);
	switch (fc & IEEE80211_FCTL_STYPE) {
	case IEEE80211_STYPE_S1G_BEACON:
		ieee80211_rx_mgmt_beacon(sdata, hdr, skb->len, rx_status);
		break;
	}
	sdata_unlock(sdata);
}

4257 4258
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
				  struct sk_buff *skb)
4259 4260 4261 4262
{
	struct ieee80211_rx_status *rx_status;
	struct ieee80211_mgmt *mgmt;
	u16 fc;
4263 4264
	struct ieee802_11_elems elems;
	int ies_len;
4265 4266 4267 4268 4269

	rx_status = (struct ieee80211_rx_status *) skb->cb;
	mgmt = (struct ieee80211_mgmt *) skb->data;
	fc = le16_to_cpu(mgmt->frame_control);

4270
	sdata_lock(sdata);
4271

J
Johannes Berg 已提交
4272 4273
	switch (fc & IEEE80211_FCTL_STYPE) {
	case IEEE80211_STYPE_BEACON:
4274 4275
		ieee80211_rx_mgmt_beacon(sdata, (void *)mgmt,
					 skb->len, rx_status);
J
Johannes Berg 已提交
4276 4277 4278 4279 4280
		break;
	case IEEE80211_STYPE_PROBE_RESP:
		ieee80211_rx_mgmt_probe_resp(sdata, skb);
		break;
	case IEEE80211_STYPE_AUTH:
4281
		ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
4282 4283
		break;
	case IEEE80211_STYPE_DEAUTH:
4284
		ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
4285 4286
		break;
	case IEEE80211_STYPE_DISASSOC:
4287
		ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
4288 4289 4290
		break;
	case IEEE80211_STYPE_ASSOC_RESP:
	case IEEE80211_STYPE_REASSOC_RESP:
4291
		ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
4292 4293
		break;
	case IEEE80211_STYPE_ACTION:
4294
		if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
4295 4296 4297
			ies_len = skb->len -
				  offsetof(struct ieee80211_mgmt,
					   u.action.u.chan_switch.variable);
4298 4299 4300 4301

			if (ies_len < 0)
				break;

4302
			/* CSA IE cannot be overridden, no need for BSSID */
4303 4304
			ieee802_11_parse_elems(
				mgmt->u.action.u.chan_switch.variable,
4305
				ies_len, true, &elems, mgmt->bssid, NULL);
4306 4307 4308 4309

			if (elems.parse_error)
				break;

4310
			ieee80211_sta_process_chanswitch(sdata,
4311 4312 4313
						 rx_status->mactime,
						 rx_status->device_timestamp,
						 &elems, false);
4314 4315 4316 4317 4318 4319 4320 4321
		} else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
			ies_len = skb->len -
				  offsetof(struct ieee80211_mgmt,
					   u.action.u.ext_chan_switch.variable);

			if (ies_len < 0)
				break;

4322 4323 4324 4325
			/*
			 * extended CSA IE can't be overridden, no need for
			 * BSSID
			 */
4326 4327
			ieee802_11_parse_elems(
				mgmt->u.action.u.ext_chan_switch.variable,
4328
				ies_len, true, &elems, mgmt->bssid, NULL);
4329 4330 4331 4332 4333 4334 4335 4336

			if (elems.parse_error)
				break;

			/* for the handling code pretend this was also an IE */
			elems.ext_chansw_ie =
				&mgmt->u.action.u.ext_chan_switch.data;

J
Johannes Berg 已提交
4337
			ieee80211_sta_process_chanswitch(sdata,
4338 4339 4340
						 rx_status->mactime,
						 rx_status->device_timestamp,
						 &elems, false);
4341
		}
4342
		break;
4343
	}
4344
	sdata_unlock(sdata);
4345 4346
}

4347
static void ieee80211_sta_timer(struct timer_list *t)
4348
{
J
Johannes Berg 已提交
4349
	struct ieee80211_sub_if_data *sdata =
4350
		from_timer(sdata, t, u.mgd.timer);
4351

4352
	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
4353 4354
}

4355 4356
void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
				   u8 *bssid, u8 reason, bool tx)
4357
{
4358
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
4359

4360
	ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
4361
			       tx, frame_buf);
4362

4363
	ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
4364
				    reason, false);
4365 4366
}

4367
static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
4368 4369 4370 4371
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
4372
	u32 tx_flags = 0;
4373 4374
	u16 trans = 1;
	u16 status = 0;
4375 4376 4377
	struct ieee80211_prep_tx_info info = {
		.subtype = IEEE80211_STYPE_AUTH,
	};
J
Johannes Berg 已提交
4378

4379
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
4380 4381 4382 4383 4384 4385 4386

	if (WARN_ON_ONCE(!auth_data))
		return -EINVAL;

	auth_data->tries++;

	if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
J
Johannes Berg 已提交
4387 4388
		sdata_info(sdata, "authentication with %pM timed out\n",
			   auth_data->bss->bssid);
J
Johannes Berg 已提交
4389 4390 4391 4392 4393 4394 4395 4396 4397 4398

		/*
		 * Most likely AP is not in the range so remove the
		 * bss struct for that AP.
		 */
		cfg80211_unlink_bss(local->hw.wiphy, auth_data->bss);

		return -ETIMEDOUT;
	}

4399
	if (auth_data->algorithm == WLAN_AUTH_SAE)
4400
		info.duration = jiffies_to_msecs(IEEE80211_AUTH_TIMEOUT_SAE);
4401

4402
	drv_mgd_prepare_tx(local, sdata, &info);
J
Johannes Berg 已提交
4403

4404 4405 4406
	sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
		   auth_data->bss->bssid, auth_data->tries,
		   IEEE80211_AUTH_MAX_TRIES);
J
Johannes Berg 已提交
4407

4408
	auth_data->expected_transaction = 2;
4409

4410 4411 4412 4413 4414
	if (auth_data->algorithm == WLAN_AUTH_SAE) {
		trans = auth_data->sae_trans;
		status = auth_data->sae_status;
		auth_data->expected_transaction = trans;
	}
J
Johannes Berg 已提交
4415

4416 4417 4418
	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
		tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
			   IEEE80211_TX_INTFL_MLME_CONN_TX;
J
Johannes Berg 已提交
4419

4420 4421 4422 4423 4424
	ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
			    auth_data->data, auth_data->data_len,
			    auth_data->bss->bssid,
			    auth_data->bss->bssid, NULL, 0, 0,
			    tx_flags);
J
Johannes Berg 已提交
4425

4426
	if (tx_flags == 0) {
4427 4428 4429 4430 4431
		if (auth_data->algorithm == WLAN_AUTH_SAE)
			auth_data->timeout = jiffies +
				IEEE80211_AUTH_TIMEOUT_SAE;
		else
			auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
4432
	} else {
4433 4434
		auth_data->timeout =
			round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
4435
	}
J
Johannes Berg 已提交
4436

4437 4438 4439
	auth_data->timeout_started = true;
	run_again(sdata, auth_data->timeout);

J
Johannes Berg 已提交
4440 4441 4442 4443 4444 4445 4446 4447
	return 0;
}

static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
	struct ieee80211_local *local = sdata->local;

4448
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
4449 4450 4451

	assoc_data->tries++;
	if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
J
Johannes Berg 已提交
4452 4453
		sdata_info(sdata, "association with %pM timed out\n",
			   assoc_data->bss->bssid);
J
Johannes Berg 已提交
4454 4455 4456 4457 4458 4459 4460 4461 4462 4463

		/*
		 * Most likely AP is not in the range so remove the
		 * bss struct for that AP.
		 */
		cfg80211_unlink_bss(local->hw.wiphy, assoc_data->bss);

		return -ETIMEDOUT;
	}

J
Johannes Berg 已提交
4464 4465 4466
	sdata_info(sdata, "associate with %pM (try %d/%d)\n",
		   assoc_data->bss->bssid, assoc_data->tries,
		   IEEE80211_ASSOC_MAX_TRIES);
J
Johannes Berg 已提交
4467 4468
	ieee80211_send_assoc(sdata);

4469
	if (!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
4470
		assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
4471
		assoc_data->timeout_started = true;
4472
		run_again(sdata, assoc_data->timeout);
4473
	} else {
4474 4475 4476 4477 4478
		assoc_data->timeout =
			round_jiffies_up(jiffies +
					 IEEE80211_ASSOC_TIMEOUT_LONG);
		assoc_data->timeout_started = true;
		run_again(sdata, assoc_data->timeout);
4479
	}
J
Johannes Berg 已提交
4480 4481 4482 4483

	return 0;
}

4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495
void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata,
				  __le16 fc, bool acked)
{
	struct ieee80211_local *local = sdata->local;

	sdata->u.mgd.status_fc = fc;
	sdata->u.mgd.status_acked = acked;
	sdata->u.mgd.status_received = true;

	ieee80211_queue_work(&local->hw, &sdata->work);
}

4496
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
4497 4498
{
	struct ieee80211_local *local = sdata->local;
4499
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
4500

4501
	sdata_lock(sdata);
4502

4503 4504 4505 4506 4507
	if (ifmgd->status_received) {
		__le16 fc = ifmgd->status_fc;
		bool status_acked = ifmgd->status_acked;

		ifmgd->status_received = false;
4508
		if (ifmgd->auth_data && ieee80211_is_auth(fc)) {
4509
			if (status_acked) {
4510 4511 4512 4513 4514 4515 4516 4517 4518
				if (ifmgd->auth_data->algorithm ==
				    WLAN_AUTH_SAE)
					ifmgd->auth_data->timeout =
						jiffies +
						IEEE80211_AUTH_TIMEOUT_SAE;
				else
					ifmgd->auth_data->timeout =
						jiffies +
						IEEE80211_AUTH_TIMEOUT_SHORT;
4519
				run_again(sdata, ifmgd->auth_data->timeout);
4520 4521 4522
			} else {
				ifmgd->auth_data->timeout = jiffies - 1;
			}
4523
			ifmgd->auth_data->timeout_started = true;
4524 4525 4526 4527 4528 4529
		} else if (ifmgd->assoc_data &&
			   (ieee80211_is_assoc_req(fc) ||
			    ieee80211_is_reassoc_req(fc))) {
			if (status_acked) {
				ifmgd->assoc_data->timeout =
					jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT;
4530
				run_again(sdata, ifmgd->assoc_data->timeout);
4531 4532 4533
			} else {
				ifmgd->assoc_data->timeout = jiffies - 1;
			}
4534
			ifmgd->assoc_data->timeout_started = true;
4535 4536 4537
		}
	}

4538
	if (ifmgd->auth_data && ifmgd->auth_data->timeout_started &&
J
Johannes Berg 已提交
4539 4540 4541 4542 4543 4544 4545
	    time_after(jiffies, ifmgd->auth_data->timeout)) {
		if (ifmgd->auth_data->done) {
			/*
			 * ok ... we waited for assoc but userspace didn't,
			 * so let's just kill the auth data
			 */
			ieee80211_destroy_auth_data(sdata, false);
4546
		} else if (ieee80211_auth(sdata)) {
J
Johannes Berg 已提交
4547
			u8 bssid[ETH_ALEN];
4548 4549 4550 4551 4552
			struct ieee80211_event event = {
				.type = MLME_EVENT,
				.u.mlme.data = AUTH_EVENT,
				.u.mlme.status = MLME_TIMEOUT,
			};
J
Johannes Berg 已提交
4553 4554 4555 4556 4557

			memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);

			ieee80211_destroy_auth_data(sdata, false);

4558
			cfg80211_auth_timeout(sdata->dev, bssid);
4559
			drv_event_callback(sdata->local, sdata, &event);
J
Johannes Berg 已提交
4560
		}
4561
	} else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
4562
		run_again(sdata, ifmgd->auth_data->timeout);
J
Johannes Berg 已提交
4563

4564
	if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
J
Johannes Berg 已提交
4565
	    time_after(jiffies, ifmgd->assoc_data->timeout)) {
4566
		if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) ||
J
Johannes Berg 已提交
4567
		    ieee80211_do_assoc(sdata)) {
4568
			struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
4569 4570 4571 4572 4573
			struct ieee80211_event event = {
				.type = MLME_EVENT,
				.u.mlme.data = ASSOC_EVENT,
				.u.mlme.status = MLME_TIMEOUT,
			};
J
Johannes Berg 已提交
4574

4575
			ieee80211_destroy_assoc_data(sdata, false, false);
4576
			cfg80211_assoc_timeout(sdata->dev, bss);
4577
			drv_event_callback(sdata->local, sdata, &event);
J
Johannes Berg 已提交
4578
		}
4579
	} else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
4580
		run_again(sdata, ifmgd->assoc_data->timeout);
J
Johannes Berg 已提交
4581

4582
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL &&
J
Johannes Berg 已提交
4583
	    ifmgd->associated) {
4584
		u8 bssid[ETH_ALEN];
4585
		int max_tries;
4586

4587
		memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
4588

4589
		if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
4590
			max_tries = max_nullfunc_tries;
4591
		else
4592
			max_tries = max_probe_tries;
4593

4594 4595 4596
		/* ACK received for nullfunc probing frame */
		if (!ifmgd->probe_send_count)
			ieee80211_reset_ap_probe(sdata);
4597 4598
		else if (ifmgd->nullfunc_failed) {
			if (ifmgd->probe_send_count < max_tries) {
J
Johannes Berg 已提交
4599 4600 4601 4602
				mlme_dbg(sdata,
					 "No ack for nullfunc frame to AP %pM, try %d/%i\n",
					 bssid, ifmgd->probe_send_count,
					 max_tries);
4603 4604
				ieee80211_mgd_probe_ap_send(sdata);
			} else {
J
Johannes Berg 已提交
4605 4606 4607
				mlme_dbg(sdata,
					 "No ack for nullfunc frame to AP %pM, disconnecting.\n",
					 bssid);
4608
				ieee80211_sta_connection_lost(sdata, bssid,
4609 4610
					WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
					false);
4611 4612
			}
		} else if (time_is_after_jiffies(ifmgd->probe_timeout))
4613
			run_again(sdata, ifmgd->probe_timeout);
4614
		else if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
J
Johannes Berg 已提交
4615 4616 4617
			mlme_dbg(sdata,
				 "Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
				 bssid, probe_wait_ms);
4618
			ieee80211_sta_connection_lost(sdata, bssid,
4619
				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false);
4620
		} else if (ifmgd->probe_send_count < max_tries) {
J
Johannes Berg 已提交
4621 4622 4623 4624
			mlme_dbg(sdata,
				 "No probe response from AP %pM after %dms, try %d/%i\n",
				 bssid, probe_wait_ms,
				 ifmgd->probe_send_count, max_tries);
4625 4626
			ieee80211_mgd_probe_ap_send(sdata);
		} else {
J
Johannes Berg 已提交
4627 4628 4629 4630
			/*
			 * We actually lost the connection ... or did we?
			 * Let's make sure!
			 */
4631 4632 4633
			mlme_dbg(sdata,
				 "No probe response from AP %pM after %dms, disconnecting.\n",
				 bssid, probe_wait_ms);
4634

4635
			ieee80211_sta_connection_lost(sdata, bssid,
4636
				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false);
J
Johannes Berg 已提交
4637 4638 4639
		}
	}

4640
	sdata_unlock(sdata);
4641 4642
}

4643
static void ieee80211_sta_bcn_mon_timer(struct timer_list *t)
J
Johannes Berg 已提交
4644 4645
{
	struct ieee80211_sub_if_data *sdata =
4646
		from_timer(sdata, t, u.mgd.bcn_mon_timer);
4647
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
4648

4649
	if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
M
Michal Kazior 已提交
4650 4651
		return;

4652 4653 4654
	if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
		return;

4655
	sdata->u.mgd.connection_loss = false;
4656 4657
	ieee80211_queue_work(&sdata->local->hw,
			     &sdata->u.mgd.beacon_connection_loss_work);
J
Johannes Berg 已提交
4658 4659
}

4660
static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
J
Johannes Berg 已提交
4661 4662
{
	struct ieee80211_sub_if_data *sdata =
4663
		from_timer(sdata, t, u.mgd.conn_mon_timer);
J
Johannes Berg 已提交
4664 4665
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_local *local = sdata->local;
4666 4667
	struct sta_info *sta;
	unsigned long timeout;
J
Johannes Berg 已提交
4668

4669
	if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
M
Michal Kazior 已提交
4670 4671
		return;

4672 4673 4674 4675 4676 4677 4678 4679 4680
	sta = sta_info_get(sdata, ifmgd->bssid);
	if (!sta)
		return;

	timeout = sta->status_stats.last_ack;
	if (time_before(sta->status_stats.last_ack, sta->rx_stats.last_rx))
		timeout = sta->rx_stats.last_rx;
	timeout += IEEE80211_CONNECTION_IDLE_TIME;

4681 4682 4683 4684
	/* If timeout is after now, then update timer to fire at
	 * the later date, but do not actually probe at this time.
	 */
	if (time_is_after_jiffies(timeout)) {
4685 4686 4687 4688
		mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
		return;
	}

4689
	ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
J
Johannes Berg 已提交
4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700
}

static void ieee80211_sta_monitor_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data,
			     u.mgd.monitor_work);

	ieee80211_mgd_probe_ap(sdata, false);
}

J
Johannes Berg 已提交
4701 4702
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
4703
	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
4704
		__ieee80211_stop_poll(sdata);
4705

J
Johannes Berg 已提交
4706
		/* let's probe the connection once */
4707
		if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
4708 4709
			ieee80211_queue_work(&sdata->local->hw,
					     &sdata->u.mgd.monitor_work);
4710
	}
J
Johannes Berg 已提交
4711
}
4712

4713
#ifdef CONFIG_PM
4714 4715 4716 4717 4718 4719 4720
void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];

	sdata_lock(sdata);

4721 4722 4723 4724 4725
	if (ifmgd->auth_data || ifmgd->assoc_data) {
		const u8 *bssid = ifmgd->auth_data ?
				ifmgd->auth_data->bss->bssid :
				ifmgd->assoc_data->bss->bssid;

4726
		/*
4727 4728 4729
		 * If we are trying to authenticate / associate while suspending,
		 * cfg80211 won't know and won't actually abort those attempts,
		 * thus we need to do that ourselves.
4730
		 */
4731
		ieee80211_send_deauth_disassoc(sdata, bssid, bssid,
4732 4733 4734
					       IEEE80211_STYPE_DEAUTH,
					       WLAN_REASON_DEAUTH_LEAVING,
					       false, frame_buf);
4735
		if (ifmgd->assoc_data)
4736
			ieee80211_destroy_assoc_data(sdata, false, true);
4737 4738
		if (ifmgd->auth_data)
			ieee80211_destroy_auth_data(sdata, false);
4739
		cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4740 4741
				      IEEE80211_DEAUTH_FRAME_LEN,
				      false);
4742 4743
	}

4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771
	/* This is a bit of a hack - we should find a better and more generic
	 * solution to this. Normally when suspending, cfg80211 will in fact
	 * deauthenticate. However, it doesn't (and cannot) stop an ongoing
	 * auth (not so important) or assoc (this is the problem) process.
	 *
	 * As a consequence, it can happen that we are in the process of both
	 * associating and suspending, and receive an association response
	 * after cfg80211 has checked if it needs to disconnect, but before
	 * we actually set the flag to drop incoming frames. This will then
	 * cause the workqueue flush to process the association response in
	 * the suspend, resulting in a successful association just before it
	 * tries to remove the interface from the driver, which now though
	 * has a channel context assigned ... this results in issues.
	 *
	 * To work around this (for now) simply deauth here again if we're
	 * now connected.
	 */
	if (ifmgd->associated && !sdata->local->wowlan) {
		u8 bssid[ETH_ALEN];
		struct cfg80211_deauth_request req = {
			.reason_code = WLAN_REASON_DEAUTH_LEAVING,
			.bssid = bssid,
		};

		memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
		ieee80211_mgd_deauth(sdata, &req);
	}

4772 4773 4774
	sdata_unlock(sdata);
}

4775 4776 4777 4778
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

4779
	sdata_lock(sdata);
4780
	if (!ifmgd->associated) {
4781
		sdata_unlock(sdata);
4782 4783 4784 4785 4786 4787 4788 4789 4790 4791
		return;
	}

	if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) {
		sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
		mlme_dbg(sdata, "driver requested disconnect after resume\n");
		ieee80211_sta_connection_lost(sdata,
					      ifmgd->associated->bssid,
					      WLAN_REASON_UNSPECIFIED,
					      true);
4792
		sdata_unlock(sdata);
4793 4794
		return;
	}
4795
	sdata_unlock(sdata);
4796 4797 4798
}
#endif

J
Johannes Berg 已提交
4799 4800
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
4801
{
4802
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
4803

4804
	ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
4805
	INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
4806
	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
4807 4808
	INIT_WORK(&ifmgd->beacon_connection_loss_work,
		  ieee80211_beacon_connection_loss_work);
4809 4810
	INIT_WORK(&ifmgd->csa_connection_drop_work,
		  ieee80211_csa_connection_drop_work);
4811
	INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
4812 4813
	INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work,
			  ieee80211_tdls_peer_del_work);
4814 4815 4816 4817
	timer_setup(&ifmgd->timer, ieee80211_sta_timer, 0);
	timer_setup(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 0);
	timer_setup(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, 0);
	timer_setup(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, 0);
4818 4819
	INIT_DELAYED_WORK(&ifmgd->tx_tspec_wk,
			  ieee80211_sta_handle_tspec_ac_params_wk);
J
Johannes Berg 已提交
4820

4821
	ifmgd->flags = 0;
4822
	ifmgd->powersave = sdata->wdev.ps;
4823 4824
	ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues;
	ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
J
Janusz Dziedzic 已提交
4825
	ifmgd->p2p_noa_index = -1;
J
Johannes Berg 已提交
4826

4827
	if (sdata->local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS)
4828 4829 4830
		ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
	else
		ifmgd->req_smps = IEEE80211_SMPS_OFF;
4831 4832 4833 4834 4835

	/* Setup TDLS data */
	spin_lock_init(&ifmgd->teardown_lock);
	ifmgd->teardown_skb = NULL;
	ifmgd->orig_teardown_skb = NULL;
4836 4837
}

4838 4839
/* scan finished notification */
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
J
Johannes Berg 已提交
4840
{
4841
	struct ieee80211_sub_if_data *sdata;
J
Johannes Berg 已提交
4842

4843 4844
	/* Restart STA timers */
	rcu_read_lock();
4845 4846 4847 4848
	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
		if (ieee80211_sdata_running(sdata))
			ieee80211_restart_sta_timer(sdata);
	}
4849 4850
	rcu_read_unlock();
}
J
Johannes Berg 已提交
4851

J
Johannes Berg 已提交
4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863
static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata,
				     struct cfg80211_bss *cbss)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	const u8 *ht_cap_ie, *vht_cap_ie;
	const struct ieee80211_ht_cap *ht_cap;
	const struct ieee80211_vht_cap *vht_cap;
	u8 chains = 1;

	if (ifmgd->flags & IEEE80211_STA_DISABLE_HT)
		return chains;

4864
	ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
J
Johannes Berg 已提交
4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876
	if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) {
		ht_cap = (void *)(ht_cap_ie + 2);
		chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
		/*
		 * TODO: use "Tx Maximum Number Spatial Streams Supported" and
		 *	 "Tx Unequal Modulation Supported" fields.
		 */
	}

	if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
		return chains;

4877
	vht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
J
Johannes Berg 已提交
4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895
	if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) {
		u8 nss;
		u16 tx_mcs_map;

		vht_cap = (void *)(vht_cap_ie + 2);
		tx_mcs_map = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
		for (nss = 8; nss > 0; nss--) {
			if (((tx_mcs_map >> (2 * (nss - 1))) & 3) !=
					IEEE80211_VHT_MCS_NOT_SUPPORTED)
				break;
		}
		/* TODO: use "Tx Highest Supported Long GI Data Rate" field? */
		chains = max(chains, nss);
	}

	return chains;
}

L
Luca Coelho 已提交
4896
static bool
4897 4898
ieee80211_verify_sta_he_mcs_support(struct ieee80211_sub_if_data *sdata,
				    struct ieee80211_supported_band *sband,
L
Luca Coelho 已提交
4899 4900 4901
				    const struct ieee80211_he_operation *he_op)
{
	const struct ieee80211_sta_he_cap *sta_he_cap =
4902 4903
		ieee80211_get_he_iftype_cap(sband,
					    ieee80211_vif_type_p2p(&sdata->vif));
4904
	u16 ap_min_req_set;
L
Luca Coelho 已提交
4905 4906 4907 4908 4909
	int i;

	if (!sta_he_cap || !he_op)
		return false;

4910 4911
	ap_min_req_set = le16_to_cpu(he_op->he_mcs_nss_set);

L
Luca Coelho 已提交
4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959
	/* Need to go over for 80MHz, 160MHz and for 80+80 */
	for (i = 0; i < 3; i++) {
		const struct ieee80211_he_mcs_nss_supp *sta_mcs_nss_supp =
			&sta_he_cap->he_mcs_nss_supp;
		u16 sta_mcs_map_rx =
			le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i]);
		u16 sta_mcs_map_tx =
			le16_to_cpu(((__le16 *)sta_mcs_nss_supp)[2 * i + 1]);
		u8 nss;
		bool verified = true;

		/*
		 * For each band there is a maximum of 8 spatial streams
		 * possible. Each of the sta_mcs_map_* is a 16-bit struct built
		 * of 2 bits per NSS (1-8), with the values defined in enum
		 * ieee80211_he_mcs_support. Need to make sure STA TX and RX
		 * capabilities aren't less than the AP's minimum requirements
		 * for this HE BSS per SS.
		 * It is enough to find one such band that meets the reqs.
		 */
		for (nss = 8; nss > 0; nss--) {
			u8 sta_rx_val = (sta_mcs_map_rx >> (2 * (nss - 1))) & 3;
			u8 sta_tx_val = (sta_mcs_map_tx >> (2 * (nss - 1))) & 3;
			u8 ap_val = (ap_min_req_set >> (2 * (nss - 1))) & 3;

			if (ap_val == IEEE80211_HE_MCS_NOT_SUPPORTED)
				continue;

			/*
			 * Make sure the HE AP doesn't require MCSs that aren't
			 * supported by the client
			 */
			if (sta_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED ||
			    sta_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED ||
			    (ap_val > sta_rx_val) || (ap_val > sta_tx_val)) {
				verified = false;
				break;
			}
		}

		if (verified)
			return true;
	}

	/* If here, STA doesn't meet AP's HE min requirements */
	return false;
}

4960 4961
static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
				  struct cfg80211_bss *cbss)
4962 4963 4964
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
4965
	const struct ieee80211_ht_cap *ht_cap = NULL;
4966
	const struct ieee80211_ht_operation *ht_oper = NULL;
J
Johannes Berg 已提交
4967
	const struct ieee80211_vht_operation *vht_oper = NULL;
L
Luca Coelho 已提交
4968
	const struct ieee80211_he_operation *he_oper = NULL;
4969
	const struct ieee80211_s1g_oper_ie *s1g_oper = NULL;
4970
	struct ieee80211_supported_band *sband;
4971
	struct cfg80211_chan_def chandef;
4972
	bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
4973
	bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ;
4974
	struct ieee80211_bss *bss = (void *)cbss->priv;
J
Johannes Berg 已提交
4975
	int ret;
4976 4977
	u32 i;
	bool have_80mhz;
4978

4979 4980
	sband = local->hw.wiphy->bands[cbss->channel->band];

J
Johannes Berg 已提交
4981 4982 4983 4984
	ifmgd->flags &= ~(IEEE80211_STA_DISABLE_40MHZ |
			  IEEE80211_STA_DISABLE_80P80MHZ |
			  IEEE80211_STA_DISABLE_160MHZ);

4985
	/* disable HT/VHT/HE if we don't support them */
4986
	if (!sband->ht_cap.ht_supported && !is_6ghz) {
4987 4988 4989 4990 4991
		ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
		ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
	}

4992
	if (!sband->vht_cap.vht_supported && is_5ghz) {
4993
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
4994 4995
		ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
	}
4996

4997 4998
	if (!ieee80211_get_he_iftype_cap(sband,
					 ieee80211_vif_type_p2p(&sdata->vif)))
4999 5000
		ifmgd->flags |= IEEE80211_STA_DISABLE_HE;

5001 5002
	rcu_read_lock();

5003
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && !is_6ghz) {
5004
		const u8 *ht_oper_ie, *ht_cap_ie;
5005

5006
		ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
5007 5008
		if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
			ht_oper = (void *)(ht_oper_ie + 2);
5009

5010 5011 5012 5013 5014
		ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
		if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap))
			ht_cap = (void *)(ht_cap_ie + 2);

		if (!ht_cap) {
5015 5016 5017
			ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
			ht_oper = NULL;
		}
5018 5019
	}

5020
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && !is_6ghz) {
5021
		const u8 *vht_oper_ie, *vht_cap;
J
Johannes Berg 已提交
5022

5023 5024
		vht_oper_ie = ieee80211_bss_get_ie(cbss,
						   WLAN_EID_VHT_OPERATION);
J
Johannes Berg 已提交
5025 5026 5027 5028
		if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper))
			vht_oper = (void *)(vht_oper_ie + 2);
		if (vht_oper && !ht_oper) {
			vht_oper = NULL;
J
Johannes Berg 已提交
5029
			sdata_info(sdata,
5030
				   "AP advertised VHT without HT, disabling HT/VHT/HE\n");
5031 5032
			ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
			ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
5033
			ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
5034
		}
5035 5036 5037 5038 5039 5040

		vht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
		if (!vht_cap || vht_cap[1] < sizeof(struct ieee80211_vht_cap)) {
			ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
			vht_oper = NULL;
		}
5041 5042
	}

5043
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) {
L
Luca Coelho 已提交
5044 5045 5046 5047 5048 5049 5050
		const struct cfg80211_bss_ies *ies;
		const u8 *he_oper_ie;

		ies = rcu_dereference(cbss->ies);
		he_oper_ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION,
						  ies->data, ies->len);
		if (he_oper_ie &&
5051
		    he_oper_ie[1] >= ieee80211_he_oper_size(&he_oper_ie[3]))
L
Luca Coelho 已提交
5052 5053 5054 5055
			he_oper = (void *)(he_oper_ie + 3);
		else
			he_oper = NULL;

5056
		if (!ieee80211_verify_sta_he_mcs_support(sdata, sband, he_oper))
L
Luca Coelho 已提交
5057 5058 5059
			ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
	}

5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073
	/* Allow VHT if at least one channel on the sband supports 80 MHz */
	have_80mhz = false;
	for (i = 0; i < sband->n_channels; i++) {
		if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
						IEEE80211_CHAN_NO_80MHZ))
			continue;

		have_80mhz = true;
		break;
	}

	if (!have_80mhz)
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;

5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085
	if (sband->band == NL80211_BAND_S1GHZ) {
		const u8 *s1g_oper_ie;

		s1g_oper_ie = ieee80211_bss_get_ie(cbss,
						   WLAN_EID_S1G_OPERATION);
		if (s1g_oper_ie && s1g_oper_ie[1] >= sizeof(*s1g_oper))
			s1g_oper = (void *)(s1g_oper_ie + 2);
		else
			sdata_info(sdata,
				   "AP missing S1G operation element?\n");
	}

J
Johannes Berg 已提交
5086 5087
	ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
						     cbss->channel,
5088
						     bss->vht_cap_info,
L
Luca Coelho 已提交
5089
						     ht_oper, vht_oper, he_oper,
5090
						     s1g_oper,
5091
						     &chandef, false);
5092

J
Johannes Berg 已提交
5093 5094
	sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
				      local->rx_chains);
5095

5096 5097
	rcu_read_unlock();

5098 5099 5100 5101 5102
	if (ifmgd->flags & IEEE80211_STA_DISABLE_HE && is_6ghz) {
		sdata_info(sdata, "Rejecting non-HE 6/7 GHz connection");
		return -EINVAL;
	}

5103 5104 5105
	/* will change later if needed */
	sdata->smps_mode = IEEE80211_SMPS_OFF;

5106
	mutex_lock(&local->mtx);
J
Johannes Berg 已提交
5107 5108 5109 5110 5111 5112 5113
	/*
	 * If this fails (possibly due to channel context sharing
	 * on incompatible channels, e.g. 80+80 and 160 sharing the
	 * same control channel) try to use a smaller bandwidth.
	 */
	ret = ieee80211_vif_use_channel(sdata, &chandef,
					IEEE80211_CHANCTX_SHARED);
5114 5115 5116 5117

	/* don't downgrade for 5 and 10 MHz channels, though. */
	if (chandef.width == NL80211_CHAN_WIDTH_5 ||
	    chandef.width == NL80211_CHAN_WIDTH_10)
5118
		goto out;
5119

5120
	while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
5121
		ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
5122 5123 5124
		ret = ieee80211_vif_use_channel(sdata, &chandef,
						IEEE80211_CHANCTX_SHARED);
	}
5125 5126
 out:
	mutex_unlock(&local->mtx);
J
Johannes Berg 已提交
5127
	return ret;
5128 5129
}

S
Sara Sharon 已提交
5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163
static bool ieee80211_get_dtim(const struct cfg80211_bss_ies *ies,
			       u8 *dtim_count, u8 *dtim_period)
{
	const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
	const u8 *idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, ies->data,
					 ies->len);
	const struct ieee80211_tim_ie *tim = NULL;
	const struct ieee80211_bssid_index *idx;
	bool valid = tim_ie && tim_ie[1] >= 2;

	if (valid)
		tim = (void *)(tim_ie + 2);

	if (dtim_count)
		*dtim_count = valid ? tim->dtim_count : 0;

	if (dtim_period)
		*dtim_period = valid ? tim->dtim_period : 0;

	/* Check if value is overridden by non-transmitted profile */
	if (!idx_ie || idx_ie[1] < 3)
		return valid;

	idx = (void *)(idx_ie + 2);

	if (dtim_count)
		*dtim_count = idx->dtim_count;

	if (dtim_period)
		*dtim_period = idx->dtim_period;

	return true;
}

5164
static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
5165 5166
				     struct cfg80211_bss *cbss, bool assoc,
				     bool override)
5167 5168 5169 5170 5171
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_bss *bss = (void *)cbss->priv;
	struct sta_info *new_sta = NULL;
5172
	struct ieee80211_supported_band *sband;
5173
	bool have_sta = false;
5174 5175
	int err;

5176 5177
	sband = local->hw.wiphy->bands[cbss->channel->band];

5178 5179 5180
	if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
		return -EINVAL;

5181 5182 5183 5184
	/* If a reconfig is happening, bail out */
	if (local->in_reconfig)
		return -EBUSY;

5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195
	if (assoc) {
		rcu_read_lock();
		have_sta = sta_info_get(sdata, cbss->bssid);
		rcu_read_unlock();
	}

	if (!have_sta) {
		new_sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
		if (!new_sta)
			return -ENOMEM;
	}
5196

5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209
	/*
	 * Set up the information for the new channel before setting the
	 * new channel. We can't - completely race-free - change the basic
	 * rates bitmap and the channel (sband) that it refers to, but if
	 * we set it up before we at least avoid calling into the driver's
	 * bss_info_changed() method with invalid information (since we do
	 * call that from changing the channel - only for IDLE and perhaps
	 * some others, but ...).
	 *
	 * So to avoid that, just set up all the new information before the
	 * channel, but tell the driver to apply it only afterwards, since
	 * it might need the new channel for that.
	 */
J
Johannes Berg 已提交
5210
	if (new_sta) {
5211 5212 5213
		u32 rates = 0, basic_rates = 0;
		bool have_higher_than_11mbit;
		int min_rate = INT_MAX, min_rate_index = -1;
J
Johannes Berg 已提交
5214
		const struct cfg80211_bss_ies *ies;
5215
		int shift = ieee80211_vif_get_shift(&sdata->vif);
5216

5217
		/* TODO: S1G Basic Rate Set is expressed elsewhere */
5218 5219
		if (cbss->channel->band == NL80211_BAND_S1GHZ) {
			ieee80211_s1g_sta_rate_init(new_sta);
5220
			goto skip_rates;
5221
		}
5222

5223 5224 5225 5226
		ieee80211_get_rates(sband, bss->supp_rates,
				    bss->supp_rates_len,
				    &rates, &basic_rates,
				    &have_higher_than_11mbit,
5227
				    &min_rate, &min_rate_index,
5228
				    shift);
5229 5230 5231 5232 5233 5234 5235 5236

		/*
		 * This used to be a workaround for basic rates missing
		 * in the association response frame. Now that we no
		 * longer use the basic rates from there, it probably
		 * doesn't happen any more, but keep the workaround so
		 * in case some *other* APs are buggy in different ways
		 * we can connect -- with a warning.
5237 5238
		 * Allow this workaround only in case the AP provided at least
		 * one rate.
5239
		 */
5240 5241 5242 5243 5244 5245 5246
		if (min_rate_index < 0) {
			sdata_info(sdata,
				   "No legacy rates in association response\n");

			sta_info_free(local, new_sta);
			return -EINVAL;
		} else if (!basic_rates) {
J
Johannes Berg 已提交
5247 5248
			sdata_info(sdata,
				   "No basic rates, using min rate instead\n");
5249 5250 5251
			basic_rates = BIT(min_rate_index);
		}

5252 5253 5254 5255 5256 5257
		if (rates)
			new_sta->sta.supp_rates[cbss->channel->band] = rates;
		else
			sdata_info(sdata,
				   "No rates found, keeping mandatory only\n");

5258 5259 5260
		sdata->vif.bss_conf.basic_rates = basic_rates;

		/* cf. IEEE 802.11 9.2.12 */
5261
		if (cbss->channel->band == NL80211_BAND_2GHZ &&
5262 5263 5264 5265 5266
		    have_higher_than_11mbit)
			sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
		else
			sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;

5267
skip_rates:
5268 5269
		memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN);

5270 5271
		/* set timing information */
		sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
J
Johannes Berg 已提交
5272
		rcu_read_lock();
5273 5274 5275 5276 5277
		ies = rcu_dereference(cbss->beacon_ies);
		if (ies) {
			sdata->vif.bss_conf.sync_tsf = ies->tsf;
			sdata->vif.bss_conf.sync_device_ts =
				bss->device_ts_beacon;
S
Sara Sharon 已提交
5278 5279 5280 5281

			ieee80211_get_dtim(ies,
					   &sdata->vif.bss_conf.sync_dtim_count,
					   NULL);
5282 5283
		} else if (!ieee80211_hw_check(&sdata->local->hw,
					       TIMING_BEACON_ONLY)) {
5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294
			ies = rcu_dereference(cbss->proberesp_ies);
			/* must be non-NULL since beacon IEs were NULL */
			sdata->vif.bss_conf.sync_tsf = ies->tsf;
			sdata->vif.bss_conf.sync_device_ts =
				bss->device_ts_presp;
			sdata->vif.bss_conf.sync_dtim_count = 0;
		} else {
			sdata->vif.bss_conf.sync_tsf = 0;
			sdata->vif.bss_conf.sync_device_ts = 0;
			sdata->vif.bss_conf.sync_dtim_count = 0;
		}
J
Johannes Berg 已提交
5295
		rcu_read_unlock();
5296
	}
5297

5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311
	if (new_sta || override) {
		err = ieee80211_prep_channel(sdata, cbss);
		if (err) {
			if (new_sta)
				sta_info_free(local, new_sta);
			return -EINVAL;
		}
	}

	if (new_sta) {
		/*
		 * tell driver about BSSID, basic rates and timing
		 * this was set up above, before setting the channel
		 */
5312
		ieee80211_bss_info_change_notify(sdata,
5313 5314
			BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |
			BSS_CHANGED_BEACON_INT);
5315 5316

		if (assoc)
J
Johannes Berg 已提交
5317
			sta_info_pre_move_state(new_sta, IEEE80211_STA_AUTH);
5318

J
Johannes Berg 已提交
5319 5320
		err = sta_info_insert(new_sta);
		new_sta = NULL;
5321
		if (err) {
J
Johannes Berg 已提交
5322 5323 5324
			sdata_info(sdata,
				   "failed to insert STA entry for the AP (error %d)\n",
				   err);
5325 5326 5327
			return err;
		}
	} else
5328
		WARN_ON_ONCE(!ether_addr_equal(ifmgd->bssid, cbss->bssid));
5329

5330 5331 5332 5333
	/* Cancel scan to ensure that nothing interferes with connection */
	if (local->scanning)
		ieee80211_scan_cancel(local);

5334 5335 5336
	return 0;
}

5337 5338 5339
/* config hooks */
int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
		       struct cfg80211_auth_request *req)
J
Johannes Berg 已提交
5340
{
J
Johannes Berg 已提交
5341 5342 5343
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_mgd_auth_data *auth_data;
5344
	u16 auth_alg;
J
Johannes Berg 已提交
5345
	int err;
5346
	bool cont_auth;
J
Johannes Berg 已提交
5347 5348

	/* prepare auth data structure */
J
Johannes Berg 已提交
5349

5350 5351 5352 5353 5354
	switch (req->auth_type) {
	case NL80211_AUTHTYPE_OPEN_SYSTEM:
		auth_alg = WLAN_AUTH_OPEN;
		break;
	case NL80211_AUTHTYPE_SHARED_KEY:
5355
		if (fips_enabled)
5356
			return -EOPNOTSUPP;
5357 5358 5359 5360 5361 5362 5363 5364
		auth_alg = WLAN_AUTH_SHARED_KEY;
		break;
	case NL80211_AUTHTYPE_FT:
		auth_alg = WLAN_AUTH_FT;
		break;
	case NL80211_AUTHTYPE_NETWORK_EAP:
		auth_alg = WLAN_AUTH_LEAP;
		break;
5365 5366 5367
	case NL80211_AUTHTYPE_SAE:
		auth_alg = WLAN_AUTH_SAE;
		break;
5368 5369 5370 5371 5372 5373 5374 5375 5376
	case NL80211_AUTHTYPE_FILS_SK:
		auth_alg = WLAN_AUTH_FILS_SK;
		break;
	case NL80211_AUTHTYPE_FILS_SK_PFS:
		auth_alg = WLAN_AUTH_FILS_SK_PFS;
		break;
	case NL80211_AUTHTYPE_FILS_PK:
		auth_alg = WLAN_AUTH_FILS_PK;
		break;
5377 5378
	default:
		return -EOPNOTSUPP;
J
Johannes Berg 已提交
5379
	}
5380

5381
	if (ifmgd->assoc_data)
5382 5383
		return -EBUSY;

5384
	auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
5385
			    req->ie_len, GFP_KERNEL);
J
Johannes Berg 已提交
5386
	if (!auth_data)
J
Johannes Berg 已提交
5387
		return -ENOMEM;
5388

J
Johannes Berg 已提交
5389
	auth_data->bss = req->bss;
5390

5391
	if (req->auth_data_len >= 4) {
5392 5393 5394 5395 5396 5397
		if (req->auth_type == NL80211_AUTHTYPE_SAE) {
			__le16 *pos = (__le16 *) req->auth_data;

			auth_data->sae_trans = le16_to_cpu(pos[0]);
			auth_data->sae_status = le16_to_cpu(pos[1]);
		}
5398 5399 5400
		memcpy(auth_data->data, req->auth_data + 4,
		       req->auth_data_len - 4);
		auth_data->data_len += req->auth_data_len - 4;
5401 5402
	}

5403 5404 5405 5406 5407 5408 5409
	/* Check if continuing authentication or trying to authenticate with the
	 * same BSS that we were in the process of authenticating with and avoid
	 * removal and re-addition of the STA entry in
	 * ieee80211_prep_connection().
	 */
	cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss;

5410
	if (req->ie && req->ie_len) {
5411 5412 5413
		memcpy(&auth_data->data[auth_data->data_len],
		       req->ie, req->ie_len);
		auth_data->data_len += req->ie_len;
J
Johannes Berg 已提交
5414
	}
5415

J
Johannes Berg 已提交
5416
	if (req->key && req->key_len) {
J
Johannes Berg 已提交
5417 5418 5419
		auth_data->key_len = req->key_len;
		auth_data->key_idx = req->key_idx;
		memcpy(auth_data->key, req->key, req->key_len);
J
Johannes Berg 已提交
5420 5421
	}

J
Johannes Berg 已提交
5422
	auth_data->algorithm = auth_alg;
J
Johannes Berg 已提交
5423

J
Johannes Berg 已提交
5424
	/* try to authenticate/probe */
5425

5426 5427 5428 5429 5430 5431 5432
	if (ifmgd->auth_data) {
		if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE) {
			auth_data->peer_confirmed =
				ifmgd->auth_data->peer_confirmed;
		}
		ieee80211_destroy_auth_data(sdata, cont_auth);
	}
5433

J
Johannes Berg 已提交
5434 5435
	/* prep auth_data so we don't go into idle on disassoc */
	ifmgd->auth_data = auth_data;
J
Johannes Berg 已提交
5436

5437 5438 5439 5440 5441 5442 5443 5444 5445
	/* If this is continuation of an ongoing SAE authentication exchange
	 * (i.e., request to send SAE Confirm) and the peer has already
	 * confirmed, mark authentication completed since we are about to send
	 * out SAE Confirm.
	 */
	if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE &&
	    auth_data->peer_confirmed && auth_data->sae_trans == 2)
		ieee80211_mark_sta_auth(sdata, req->bss->bssid);

5446 5447 5448
	if (ifmgd->associated) {
		u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];

5449 5450 5451
		sdata_info(sdata,
			   "disconnect from AP %pM for new auth to %pM\n",
			   ifmgd->associated->bssid, req->bss->bssid);
5452 5453 5454 5455
		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       WLAN_REASON_UNSPECIFIED,
				       false, frame_buf);

5456 5457
		ieee80211_report_disconnect(sdata, frame_buf,
					    sizeof(frame_buf), true,
5458 5459
					    WLAN_REASON_UNSPECIFIED,
					    false);
5460
	}
J
Johannes Berg 已提交
5461

J
Johannes Berg 已提交
5462
	sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
5463

5464
	err = ieee80211_prep_connection(sdata, req->bss, cont_auth, false);
5465
	if (err)
J
Johannes Berg 已提交
5466
		goto err_clear;
J
Johannes Berg 已提交
5467

5468
	err = ieee80211_auth(sdata);
J
Johannes Berg 已提交
5469 5470 5471 5472 5473 5474
	if (err) {
		sta_info_destroy_addr(sdata, req->bss->bssid);
		goto err_clear;
	}

	/* hold our own reference */
5475
	cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
5476
	return 0;
J
Johannes Berg 已提交
5477 5478

 err_clear:
5479
	eth_zero_addr(ifmgd->bssid);
5480
	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
J
Johannes Berg 已提交
5481
	ifmgd->auth_data = NULL;
5482 5483 5484
	mutex_lock(&sdata->local->mtx);
	ieee80211_vif_release_channel(sdata);
	mutex_unlock(&sdata->local->mtx);
J
Johannes Berg 已提交
5485 5486
	kfree(auth_data);
	return err;
J
Johannes Berg 已提交
5487 5488
}

5489 5490
int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
			struct cfg80211_assoc_request *req)
5491
{
5492
	bool is_6ghz = req->bss->channel->band == NL80211_BAND_6GHZ;
5493
	bool is_5ghz = req->bss->channel->band == NL80211_BAND_5GHZ;
J
Johannes Berg 已提交
5494
	struct ieee80211_local *local = sdata->local;
5495
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
5496
	struct ieee80211_bss *bss = (void *)req->bss->priv;
J
Johannes Berg 已提交
5497
	struct ieee80211_mgd_assoc_data *assoc_data;
5498
	const struct cfg80211_bss_ies *beacon_ies;
J
Johannes Berg 已提交
5499
	struct ieee80211_supported_band *sband;
5500
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
5501
	const u8 *ssidie, *ht_ie, *vht_ie;
5502
	int i, err;
5503
	bool override = false;
5504

J
Johannes Berg 已提交
5505 5506 5507 5508
	assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL);
	if (!assoc_data)
		return -ENOMEM;

5509 5510
	rcu_read_lock();
	ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
5511
	if (!ssidie || ssidie[1] > sizeof(assoc_data->ssid)) {
5512 5513 5514 5515 5516 5517
		rcu_read_unlock();
		kfree(assoc_data);
		return -EINVAL;
	}
	memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
	assoc_data->ssid_len = ssidie[1];
5518 5519
	memcpy(bss_conf->ssid, assoc_data->ssid, assoc_data->ssid_len);
	bss_conf->ssid_len = assoc_data->ssid_len;
5520 5521
	rcu_read_unlock();

5522 5523 5524
	if (ifmgd->associated) {
		u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];

5525 5526 5527
		sdata_info(sdata,
			   "disconnect from AP %pM for new assoc to %pM\n",
			   ifmgd->associated->bssid, req->bss->bssid);
5528 5529 5530 5531
		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       WLAN_REASON_UNSPECIFIED,
				       false, frame_buf);

5532 5533
		ieee80211_report_disconnect(sdata, frame_buf,
					    sizeof(frame_buf), true,
5534 5535
					    WLAN_REASON_UNSPECIFIED,
					    false);
5536
	}
J
Johannes Berg 已提交
5537 5538 5539 5540

	if (ifmgd->auth_data && !ifmgd->auth_data->done) {
		err = -EBUSY;
		goto err_free;
J
Johannes Berg 已提交
5541
	}
5542

J
Johannes Berg 已提交
5543 5544 5545 5546
	if (ifmgd->assoc_data) {
		err = -EBUSY;
		goto err_free;
	}
5547

J
Johannes Berg 已提交
5548 5549 5550 5551
	if (ifmgd->auth_data) {
		bool match;

		/* keep sta info, bssid if matching */
5552
		match = ether_addr_equal(ifmgd->bssid, req->bss->bssid);
J
Johannes Berg 已提交
5553
		ieee80211_destroy_auth_data(sdata, match);
5554 5555
	}

J
Johannes Berg 已提交
5556
	/* prepare assoc data */
5557

5558 5559
	ifmgd->beacon_crc_valid = false;

5560 5561 5562
	assoc_data->wmm = bss->wmm_used &&
			  (local->hw.queues >= IEEE80211_NUM_ACS);

J
Johannes Berg 已提交
5563 5564 5565 5566 5567 5568 5569
	/*
	 * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode.
	 * We still associate in non-HT mode (11a/b/g) if any one of these
	 * ciphers is configured as pairwise.
	 * We can set this to true for non-11n hardware, that'll be checked
	 * separately along with the peer capabilities.
	 */
5570
	for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) {
5571 5572
		if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
		    req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
5573
		    req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
5574
			ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
5575
			ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
L
Luca Coelho 已提交
5576
			ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
5577
			netdev_info(sdata->dev,
5578
				    "disabling HT/VHT/HE due to WEP/TKIP use\n");
5579 5580
		}
	}
5581

J
Johannes Berg 已提交
5582 5583
	sband = local->hw.wiphy->bands[req->bss->channel->band];

5584 5585 5586
	/* also disable HT/VHT/HE if the AP doesn't use WMM */
	if (!bss->wmm_used) {
		ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
5587
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
5588 5589 5590
		ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
		netdev_info(sdata->dev,
			    "disabling HT/VHT/HE as WMM/QoS is not supported by the AP\n");
5591 5592
	}

B
Ben Greear 已提交
5593 5594 5595 5596
	memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
	memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
	       sizeof(ifmgd->ht_capa_mask));

5597 5598 5599 5600
	memcpy(&ifmgd->vht_capa, &req->vht_capa, sizeof(ifmgd->vht_capa));
	memcpy(&ifmgd->vht_capa_mask, &req->vht_capa_mask,
	       sizeof(ifmgd->vht_capa_mask));

5601 5602 5603 5604
	memcpy(&ifmgd->s1g_capa, &req->s1g_capa, sizeof(ifmgd->s1g_capa));
	memcpy(&ifmgd->s1g_capa_mask, &req->s1g_capa_mask,
	       sizeof(ifmgd->s1g_capa_mask));

5605
	if (req->ie && req->ie_len) {
J
Johannes Berg 已提交
5606 5607 5608
		memcpy(assoc_data->ie, req->ie, req->ie_len);
		assoc_data->ie_len = req->ie_len;
	}
5609

5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624
	if (req->fils_kek) {
		/* should already be checked in cfg80211 - so warn */
		if (WARN_ON(req->fils_kek_len > FILS_MAX_KEK_LEN)) {
			err = -EINVAL;
			goto err_free;
		}
		memcpy(assoc_data->fils_kek, req->fils_kek,
		       req->fils_kek_len);
		assoc_data->fils_kek_len = req->fils_kek_len;
	}

	if (req->fils_nonces)
		memcpy(assoc_data->fils_nonces, req->fils_nonces,
		       2 * FILS_NONCE_LEN);

J
Johannes Berg 已提交
5625 5626 5627 5628
	assoc_data->bss = req->bss;
	assoc_data->capability = req->bss->capability;
	assoc_data->supp_rates = bss->supp_rates;
	assoc_data->supp_rates_len = bss->supp_rates_len;
5629

5630
	rcu_read_lock();
5631 5632 5633 5634
	ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION);
	if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation))
		assoc_data->ap_ht_param =
			((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param;
5635
	else if (!is_6ghz)
5636
		ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
5637 5638 5639 5640
	vht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_VHT_CAPABILITY);
	if (vht_ie && vht_ie[1] >= sizeof(struct ieee80211_vht_cap))
		memcpy(&assoc_data->ap_vht_cap, vht_ie + 2,
		       sizeof(struct ieee80211_vht_cap));
5641
	else if (is_5ghz)
5642 5643
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT |
				IEEE80211_STA_DISABLE_HE;
5644
	rcu_read_unlock();
5645

5646
	if (WARN((sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD) &&
5647
		 ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK),
5648 5649 5650
	     "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"))
		sdata->vif.driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD;

K
Kalle Valo 已提交
5651
	if (bss->wmm_used && bss->uapsd_supported &&
5652
	    (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD)) {
5653
		assoc_data->uapsd = true;
K
Kalle Valo 已提交
5654 5655
		ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
	} else {
5656
		assoc_data->uapsd = false;
K
Kalle Valo 已提交
5657 5658 5659
		ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
	}

5660
	if (req->prev_bssid)
J
Johannes Berg 已提交
5661
		memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN);
5662 5663 5664 5665 5666 5667 5668 5669 5670

	if (req->use_mfp) {
		ifmgd->mfp = IEEE80211_MFP_REQUIRED;
		ifmgd->flags |= IEEE80211_STA_MFP_ENABLED;
	} else {
		ifmgd->mfp = IEEE80211_MFP_DISABLED;
		ifmgd->flags &= ~IEEE80211_STA_MFP_ENABLED;
	}

5671 5672 5673 5674 5675
	if (req->flags & ASSOC_REQ_USE_RRM)
		ifmgd->flags |= IEEE80211_STA_ENABLE_RRM;
	else
		ifmgd->flags &= ~IEEE80211_STA_ENABLE_RRM;

5676 5677 5678 5679 5680
	if (req->crypto.control_port)
		ifmgd->flags |= IEEE80211_STA_CONTROL_PORT;
	else
		ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;

5681 5682
	sdata->control_port_protocol = req->crypto.control_port_ethertype;
	sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
5683 5684
	sdata->control_port_over_nl80211 =
					req->crypto.control_port_over_nl80211;
5685
	sdata->control_port_no_preauth = req->crypto.control_port_no_preauth;
5686 5687
	sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
							sdata->vif.type);
5688

J
Johannes Berg 已提交
5689 5690 5691
	/* kick off associate process */

	ifmgd->assoc_data = assoc_data;
5692
	ifmgd->dtim_period = 0;
5693
	ifmgd->have_beacon = false;
J
Johannes Berg 已提交
5694

5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718
	/* override HT/VHT configuration only if the AP and we support it */
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
		struct ieee80211_sta_ht_cap sta_ht_cap;

		if (req->flags & ASSOC_REQ_DISABLE_HT)
			override = true;

		memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
		ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);

		/* check for 40 MHz disable override */
		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ) &&
		    sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
		    !(sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
			override = true;

		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
		    req->flags & ASSOC_REQ_DISABLE_VHT)
			override = true;
	}

	if (req->flags & ASSOC_REQ_DISABLE_HT) {
		ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
5719
		ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
5720 5721 5722 5723 5724
	}

	if (req->flags & ASSOC_REQ_DISABLE_VHT)
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;

5725 5726 5727
	if (req->flags & ASSOC_REQ_DISABLE_HE)
		ifmgd->flags |= IEEE80211_STA_DISABLE_HE;

5728
	err = ieee80211_prep_connection(sdata, req->bss, true, override);
5729 5730
	if (err)
		goto err_clear;
J
Johannes Berg 已提交
5731

5732 5733 5734 5735 5736 5737 5738 5739 5740
	if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
		if (ifmgd->powersave)
			sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
		else
			sdata->smps_mode = IEEE80211_SMPS_OFF;
	} else {
		sdata->smps_mode = ifmgd->req_smps;
	}

5741 5742
	rcu_read_lock();
	beacon_ies = rcu_dereference(req->bss->beacon_ies);
5743

5744
	if (ieee80211_hw_check(&sdata->local->hw, NEED_DTIM_BEFORE_ASSOC) &&
5745 5746 5747 5748 5749 5750 5751 5752
	    !beacon_ies) {
		/*
		 * Wait up to one beacon interval ...
		 * should this be more if we miss one?
		 */
		sdata_info(sdata, "waiting for beacon from %pM\n",
			   ifmgd->bssid);
		assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
5753
		assoc_data->timeout_started = true;
5754 5755
		assoc_data->need_beacon = true;
	} else if (beacon_ies) {
5756
		const struct element *elem;
5757 5758
		u8 dtim_count = 0;

S
Sara Sharon 已提交
5759 5760 5761
		ieee80211_get_dtim(beacon_ies, &dtim_count,
				   &ifmgd->dtim_period);

5762
		ifmgd->have_beacon = true;
J
Johannes Berg 已提交
5763
		assoc_data->timeout = jiffies;
5764
		assoc_data->timeout_started = true;
5765

5766
		if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
5767 5768 5769 5770 5771
			sdata->vif.bss_conf.sync_tsf = beacon_ies->tsf;
			sdata->vif.bss_conf.sync_device_ts =
				bss->device_ts_beacon;
			sdata->vif.bss_conf.sync_dtim_count = dtim_count;
		}
S
Sara Sharon 已提交
5772

5773 5774 5775 5776
		elem = cfg80211_find_ext_elem(WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION,
					      beacon_ies->data, beacon_ies->len);
		if (elem && elem->datalen >= 3)
			sdata->vif.bss_conf.profile_periodicity = elem->data[2];
5777 5778
		else
			sdata->vif.bss_conf.profile_periodicity = 0;
S
Sara Sharon 已提交
5779

5780 5781 5782 5783
		elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
					  beacon_ies->data, beacon_ies->len);
		if (elem && elem->datalen >= 11 &&
		    (elem->data[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
S
Sara Sharon 已提交
5784
			sdata->vif.bss_conf.ema_ap = true;
5785 5786
		else
			sdata->vif.bss_conf.ema_ap = false;
5787 5788
	} else {
		assoc_data->timeout = jiffies;
5789
		assoc_data->timeout_started = true;
J
Johannes Berg 已提交
5790
	}
5791 5792
	rcu_read_unlock();

5793
	run_again(sdata, assoc_data->timeout);
J
Johannes Berg 已提交
5794

P
Paul Stewart 已提交
5795 5796 5797 5798 5799 5800 5801 5802 5803 5804
	if (bss->corrupt_data) {
		char *corrupt_type = "data";
		if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_BEACON) {
			if (bss->corrupt_data &
					IEEE80211_BSS_CORRUPT_PROBE_RESP)
				corrupt_type = "beacon and probe response";
			else
				corrupt_type = "beacon";
		} else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP)
			corrupt_type = "probe response";
J
Johannes Berg 已提交
5805 5806
		sdata_info(sdata, "associating with AP with corrupt %s\n",
			   corrupt_type);
P
Paul Stewart 已提交
5807 5808
	}

5809
	return 0;
J
Johannes Berg 已提交
5810
 err_clear:
5811
	eth_zero_addr(ifmgd->bssid);
5812
	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
J
Johannes Berg 已提交
5813 5814 5815 5816
	ifmgd->assoc_data = NULL;
 err_free:
	kfree(assoc_data);
	return err;
5817 5818
}

5819
int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
5820
			 struct cfg80211_deauth_request *req)
5821
{
5822
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
5823
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
5824
	bool tx = !req->local_state_change;
5825 5826 5827
	struct ieee80211_prep_tx_info info = {
		.subtype = IEEE80211_STYPE_DEAUTH,
	};
5828

5829 5830 5831 5832 5833 5834
	if (ifmgd->auth_data &&
	    ether_addr_equal(ifmgd->auth_data->bss->bssid, req->bssid)) {
		sdata_info(sdata,
			   "aborting authentication with %pM by local choice (Reason: %u=%s)\n",
			   req->bssid, req->reason_code,
			   ieee80211_get_reason_code_string(req->reason_code));
5835

5836
		drv_mgd_prepare_tx(sdata->local, sdata, &info);
5837
		ieee80211_send_deauth_disassoc(sdata, req->bssid, req->bssid,
5838
					       IEEE80211_STYPE_DEAUTH,
5839
					       req->reason_code, tx,
5840
					       frame_buf);
5841
		ieee80211_destroy_auth_data(sdata, false);
5842 5843
		ieee80211_report_disconnect(sdata, frame_buf,
					    sizeof(frame_buf), true,
5844
					    req->reason_code, false);
5845
		drv_mgd_complete_tx(sdata->local, sdata, &info);
5846
		return 0;
5847 5848
	}

5849 5850 5851 5852 5853 5854 5855
	if (ifmgd->assoc_data &&
	    ether_addr_equal(ifmgd->assoc_data->bss->bssid, req->bssid)) {
		sdata_info(sdata,
			   "aborting association with %pM by local choice (Reason: %u=%s)\n",
			   req->bssid, req->reason_code,
			   ieee80211_get_reason_code_string(req->reason_code));

5856
		drv_mgd_prepare_tx(sdata->local, sdata, &info);
5857
		ieee80211_send_deauth_disassoc(sdata, req->bssid, req->bssid,
5858 5859 5860
					       IEEE80211_STYPE_DEAUTH,
					       req->reason_code, tx,
					       frame_buf);
5861
		ieee80211_destroy_assoc_data(sdata, false, true);
5862 5863
		ieee80211_report_disconnect(sdata, frame_buf,
					    sizeof(frame_buf), true,
5864
					    req->reason_code, false);
5865 5866 5867
		return 0;
	}

5868 5869
	if (ifmgd->associated &&
	    ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
5870 5871 5872 5873 5874
		sdata_info(sdata,
			   "deauthenticating from %pM by local choice (Reason: %u=%s)\n",
			   req->bssid, req->reason_code,
			   ieee80211_get_reason_code_string(req->reason_code));

5875 5876
		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       req->reason_code, tx, frame_buf);
5877 5878
		ieee80211_report_disconnect(sdata, frame_buf,
					    sizeof(frame_buf), true,
5879
					    req->reason_code, false);
5880
		drv_mgd_complete_tx(sdata->local, sdata, &info);
5881 5882
		return 0;
	}
5883

5884
	return -ENOTCONN;
5885
}
5886

5887
int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
5888
			   struct cfg80211_disassoc_request *req)
J
Johannes Berg 已提交
5889
{
5890
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
5891
	u8 bssid[ETH_ALEN];
5892
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
J
Johannes Berg 已提交
5893

J
Johannes Berg 已提交
5894 5895 5896 5897 5898 5899
	/*
	 * cfg80211 should catch this ... but it's racy since
	 * we can receive a disassoc frame, process it, hand it
	 * to cfg80211 while that's in a locked section already
	 * trying to tell us that the user wants to disconnect.
	 */
5900
	if (ifmgd->associated != req->bss)
5901 5902
		return -ENOLINK;

J
Johannes Berg 已提交
5903
	sdata_info(sdata,
5904 5905
		   "disassociating from %pM by local choice (Reason: %u=%s)\n",
		   req->bss->bssid, req->reason_code, ieee80211_get_reason_code_string(req->reason_code));
5906

5907
	memcpy(bssid, req->bss->bssid, ETH_ALEN);
5908 5909 5910
	ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
			       req->reason_code, !req->local_state_change,
			       frame_buf);
5911

5912
	ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
5913
				    req->reason_code, false);
5914

5915 5916
	return 0;
}
5917

5918
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
5919 5920 5921
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

5922 5923 5924 5925 5926 5927 5928 5929 5930 5931
	/*
	 * Make sure some work items will not run after this,
	 * they will not do anything but might not have been
	 * cancelled when disconnecting.
	 */
	cancel_work_sync(&ifmgd->monitor_work);
	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
	cancel_work_sync(&ifmgd->request_smps_work);
	cancel_work_sync(&ifmgd->csa_connection_drop_work);
	cancel_work_sync(&ifmgd->chswitch_work);
5932
	cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work);
5933

5934
	sdata_lock(sdata);
5935 5936
	if (ifmgd->assoc_data) {
		struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
5937
		ieee80211_destroy_assoc_data(sdata, false, false);
5938 5939
		cfg80211_assoc_timeout(sdata->dev, bss);
	}
5940 5941
	if (ifmgd->auth_data)
		ieee80211_destroy_auth_data(sdata, false);
5942 5943 5944 5945 5946 5947
	spin_lock_bh(&ifmgd->teardown_lock);
	if (ifmgd->teardown_skb) {
		kfree_skb(ifmgd->teardown_skb);
		ifmgd->teardown_skb = NULL;
		ifmgd->orig_teardown_skb = NULL;
	}
5948 5949 5950
	kfree(ifmgd->assoc_req_ies);
	ifmgd->assoc_req_ies = NULL;
	ifmgd->assoc_req_ies_len = 0;
5951
	spin_unlock_bh(&ifmgd->teardown_lock);
5952
	del_timer_sync(&ifmgd->timer);
5953
	sdata_unlock(sdata);
5954 5955
}

5956 5957
void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
			       enum nl80211_cqm_rssi_threshold_event rssi_event,
5958
			       s32 rssi_level,
5959 5960 5961 5962
			       gfp_t gfp)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);

5963
	trace_api_cqm_rssi_notify(sdata, rssi_event, rssi_level);
J
Johannes Berg 已提交
5964

5965
	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, rssi_level, gfp);
5966 5967
}
EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
5968 5969 5970 5971 5972 5973 5974 5975 5976 5977

void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);

	trace_api_cqm_beacon_loss_notify(sdata->local, sdata);

	cfg80211_cqm_beacon_loss_notify(sdata->dev, gfp);
}
EXPORT_SYMBOL(ieee80211_cqm_beacon_loss_notify);