mlme.c 122.4 KB
Newer Older
1 2
/*
 * BSS client mode implementation
3
 * Copyright 2003-2008, Jouni Malinen <j@w1.fi>
4 5 6 7 8 9 10 11 12 13
 * 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>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

14
#include <linux/delay.h>
15 16 17 18
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
19
#include <linux/moduleparam.h>
20
#include <linux/rtnetlink.h>
21
#include <linux/pm_qos.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

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

43 44 45 46 47 48 49 50 51
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 已提交
52 53

/*
54 55 56 57 58 59
 * 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 已提交
60
 */
61 62 63 64
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.");
65

J
Johannes Berg 已提交
66 67 68 69
/*
 * Time the connection can be idle before we probe
 * it to see if we can still talk to the AP.
 */
70
#define IEEE80211_CONNECTION_IDLE_TIME	(30 * HZ)
J
Johannes Berg 已提交
71 72 73 74 75
/*
 * Time we wait for a probe response after sending
 * a probe request because of beacon loss or for
 * checking the connection still works.
 */
76 77 78 79 80
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).");
81

82 83 84 85 86 87 88
/*
 * Weight given to the latest Beacon frame when calculating average signal
 * strength for Beacon frames received in the current BSS. This must be
 * between 1 and 15.
 */
#define IEEE80211_SIGNAL_AVE_WEIGHT	3

89 90 91 92 93 94
/*
 * 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 已提交
95 96 97 98 99 100 101 102 103 104
/*
 * 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.
 */
105 106
static void run_again(struct ieee80211_sub_if_data *sdata,
		      unsigned long timeout)
J
Johannes Berg 已提交
107
{
108
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
109

110 111 112
	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 已提交
113 114
}

115
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
116
{
117
	if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
J
Johannes Berg 已提交
118 119
		return;

120 121 122
	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
		return;

J
Johannes Berg 已提交
123
	mod_timer(&sdata->u.mgd.bcn_mon_timer,
124
		  round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout));
J
Johannes Berg 已提交
125 126
}

127 128
void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
{
129 130
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

131 132 133
	if (unlikely(!sdata->u.mgd.associated))
		return;

134 135 136 137 138
	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
		return;

	mod_timer(&sdata->u.mgd.conn_mon_timer,
		  round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
139 140

	ifmgd->probe_send_count = 0;
141 142
}

143
static int ecw2cw(int ecw)
J
Johannes Berg 已提交
144
{
145
	return (1 << ecw) - 1;
J
Johannes Berg 已提交
146 147
}

148 149 150 151 152 153
static u32
ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_supported_band *sband,
			     struct ieee80211_channel *channel,
			     const struct ieee80211_ht_operation *ht_oper,
			     const struct ieee80211_vht_operation *vht_oper,
154
			     struct cfg80211_chan_def *chandef, bool tracking)
155
{
156
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
	struct cfg80211_chan_def vht_chandef;
	u32 ht_cfreq, ret;

	chandef->chan = channel;
	chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
	chandef->center_freq1 = channel->center_freq;
	chandef->center_freq2 = 0;

	if (!ht_oper || !sband->ht_cap.ht_supported) {
		ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
		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 */
175
	if (!tracking && channel->center_freq != ht_cfreq) {
176 177 178 179 180 181 182
		/*
		 * 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.
		 */
183 184 185 186
		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);
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
		ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
		goto out;
	}

	/* check 40 MHz support, if we have it */
	if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
		switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
			chandef->width = NL80211_CHAN_WIDTH_40;
			chandef->center_freq1 += 10;
			break;
		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
			chandef->width = NL80211_CHAN_WIDTH_40;
			chandef->center_freq1 -= 10;
			break;
		}
	} else {
		/* 40 MHz (and 80 MHz) must be supported for VHT */
		ret = IEEE80211_STA_DISABLE_VHT;
206 207
		/* also mark 40 MHz disabled */
		ret |= IEEE80211_STA_DISABLE_40MHZ;
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
		goto out;
	}

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

	vht_chandef.chan = channel;
	vht_chandef.center_freq1 =
		ieee80211_channel_to_frequency(vht_oper->center_freq_seg1_idx,
					       channel->band);
	vht_chandef.center_freq2 = 0;

	switch (vht_oper->chan_width) {
	case IEEE80211_VHT_CHANWIDTH_USE_HT:
		vht_chandef.width = chandef->width;
		break;
	case IEEE80211_VHT_CHANWIDTH_80MHZ:
		vht_chandef.width = NL80211_CHAN_WIDTH_80;
		break;
	case IEEE80211_VHT_CHANWIDTH_160MHZ:
		vht_chandef.width = NL80211_CHAN_WIDTH_160;
		break;
	case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
		vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
234 235 236 237
		vht_chandef.center_freq2 =
			ieee80211_channel_to_frequency(
				vht_oper->center_freq_seg2_idx,
				channel->band);
238 239
		break;
	default:
240
		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
241 242 243
			sdata_info(sdata,
				   "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
				   vht_oper->chan_width);
244 245 246 247 248
		ret = IEEE80211_STA_DISABLE_VHT;
		goto out;
	}

	if (!cfg80211_chandef_valid(&vht_chandef)) {
249
		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
250 251
			sdata_info(sdata,
				   "AP VHT information is invalid, disable VHT\n");
252 253 254 255 256 257 258 259 260 261
		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)) {
262
		if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
263 264
			sdata_info(sdata,
				   "AP VHT information doesn't match HT, disable VHT\n");
265 266 267 268 269 270 271 272 273
		ret = IEEE80211_STA_DISABLE_VHT;
		goto out;
	}

	*chandef = vht_chandef;

	ret = 0;

out:
274 275 276 277
	/* don't print the message below for VHT mismatch if VHT is disabled */
	if (ret & IEEE80211_STA_DISABLE_VHT)
		vht_chandef = *chandef;

278 279 280 281 282 283 284 285
	/*
	 * 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.
	 */
286
	while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
287 288
					tracking ? 0 :
						   IEEE80211_CHAN_DISABLED)) {
289 290 291
		if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
			ret = IEEE80211_STA_DISABLE_HT |
			      IEEE80211_STA_DISABLE_VHT;
292
			break;
293 294
		}

295
		ret |= ieee80211_chandef_downgrade(chandef);
296 297
	}

298
	if (chandef->width != vht_chandef.width && !tracking)
299 300 301 302 303 304 305
		sdata_info(sdata,
			   "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");

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

306 307 308 309 310
static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
			       struct sta_info *sta,
			       const struct ieee80211_ht_operation *ht_oper,
			       const struct ieee80211_vht_operation *vht_oper,
			       const u8 *bssid, u32 *changed)
311 312
{
	struct ieee80211_local *local = sdata->local;
313
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
314
	struct ieee80211_supported_band *sband;
J
Johannes Berg 已提交
315
	struct ieee80211_channel *chan;
316
	struct cfg80211_chan_def chandef;
317
	u16 ht_opmode;
318 319 320
	u32 flags;
	enum ieee80211_sta_rx_bandwidth new_sta_bw;
	int ret;
321

322 323
	/* if HT was/is disabled, don't track any bandwidth changes */
	if (ifmgd->flags & IEEE80211_STA_DISABLE_HT || !ht_oper)
324 325
		return 0;

326 327 328 329 330 331 332
	/* don't check VHT if we associated as non-VHT station */
	if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
		vht_oper = NULL;

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

333
	chan = sdata->vif.bss_conf.chandef.chan;
J
Johannes Berg 已提交
334
	sband = local->hw.wiphy->bands[chan->band];
335

336 337
	/* calculate new channel (type) based on HT/VHT operation IEs */
	flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
338
					     vht_oper, &chandef, true);
339 340 341 342 343 344 345 346 347 348

	/*
	 * 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)
349
		flags |= ieee80211_chandef_downgrade(&chandef);
350 351
	if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ &&
	    chandef.width == NL80211_CHAN_WIDTH_160)
352
		flags |= ieee80211_chandef_downgrade(&chandef);
353 354
	if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ &&
	    chandef.width > NL80211_CHAN_WIDTH_20)
355
		flags |= ieee80211_chandef_downgrade(&chandef);
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381

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

	sdata_info(sdata,
		   "AP %pM changed bandwidth, new config is %d MHz, width %d (%d/%d MHz)\n",
		   ifmgd->bssid, chandef.chan->center_freq, chandef.width,
		   chandef.center_freq1, chandef.center_freq2);

	if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
				      IEEE80211_STA_DISABLE_VHT |
				      IEEE80211_STA_DISABLE_40MHZ |
				      IEEE80211_STA_DISABLE_80P80MHZ |
				      IEEE80211_STA_DISABLE_160MHZ)) ||
	    !cfg80211_chandef_valid(&chandef)) {
		sdata_info(sdata,
			   "AP %pM changed bandwidth in a way we can't support - disconnect\n",
			   ifmgd->bssid);
		return -EINVAL;
	}

	switch (chandef.width) {
	case NL80211_CHAN_WIDTH_20_NOHT:
	case NL80211_CHAN_WIDTH_20:
		new_sta_bw = IEEE80211_STA_RX_BW_20;
		break;
382
	case NL80211_CHAN_WIDTH_40:
383
		new_sta_bw = IEEE80211_STA_RX_BW_40;
384
		break;
385 386 387 388 389 390
	case NL80211_CHAN_WIDTH_80:
		new_sta_bw = IEEE80211_STA_RX_BW_80;
		break;
	case NL80211_CHAN_WIDTH_80P80:
	case NL80211_CHAN_WIDTH_160:
		new_sta_bw = IEEE80211_STA_RX_BW_160;
391
		break;
392 393
	default:
		return -EINVAL;
394
	}
395

396 397
	if (new_sta_bw > sta->cur_max_bandwidth)
		new_sta_bw = sta->cur_max_bandwidth;
398

399 400 401 402 403
	if (new_sta_bw < sta->sta.bandwidth) {
		sta->sta.bandwidth = new_sta_bw;
		rate_control_rate_update(local, sband, sta,
					 IEEE80211_RC_BW_CHANGED);
	}
404

405 406 407 408 409 410 411
	ret = ieee80211_vif_change_bandwidth(sdata, &chandef, changed);
	if (ret) {
		sdata_info(sdata,
			   "AP %pM changed bandwidth to incompatible one - disconnect\n",
			   ifmgd->bssid);
		return ret;
	}
412

413 414 415 416
	if (new_sta_bw > sta->sta.bandwidth) {
		sta->sta.bandwidth = new_sta_bw;
		rate_control_rate_update(local, sband, sta,
					 IEEE80211_RC_BW_CHANGED);
417
	}
418

419
	ht_opmode = le16_to_cpu(ht_oper->operation_mode);
420 421

	/* if bss configuration changed store the new one */
422 423
	if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
		*changed |= BSS_CHANGED_HT;
424
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
425 426
	}

427
	return 0;
428 429
}

J
Johannes Berg 已提交
430 431
/* frame sending functions */

J
Johannes Berg 已提交
432
static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
433
				struct sk_buff *skb, u8 ap_ht_param,
J
Johannes Berg 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
				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;

451
	switch (ap_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
J
Johannes Berg 已提交
452 453 454 455 456 457 458 459 460 461 462 463 464 465
	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;
	}

466 467 468 469 470 471 472 473 474 475
	/*
	 * 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 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
	/* 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);
	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);
}

501 502
static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
				 struct sk_buff *skb,
503 504
				 struct ieee80211_supported_band *sband,
				 struct ieee80211_vht_cap *ap_vht_cap)
505 506 507 508 509 510 511 512
{
	u8 *pos;
	u32 cap;
	struct ieee80211_sta_vht_cap vht_cap;

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

	memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
513
	ieee80211_apply_vhtcap_overrides(sdata, &vht_cap);
514 515 516 517

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

J
Johannes Berg 已提交
518 519 520 521 522 523 524 525 526 527
	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) {
		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
		cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
	}

	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) {
		cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
	}

528 529 530 531 532 533 534 535
	/*
	 * 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)))
		cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;

536
	/* reserve and fill IE */
M
Mahesh Palivela 已提交
537
	pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
538 539 540
	ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
}

J
Johannes Berg 已提交
541 542 543 544 545 546 547 548 549
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;
	u8 *pos, qos_info;
	size_t offset = 0, noffset;
550
	int i, count, rates_len, supp_rates_len, shift;
J
Johannes Berg 已提交
551 552
	u16 capab;
	struct ieee80211_supported_band *sband;
J
Johannes Berg 已提交
553 554
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_channel *chan;
555
	u32 rate_flags, rates = 0;
J
Johannes Berg 已提交
556

557
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
558

J
Johannes Berg 已提交
559 560 561 562 563 564
	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
	if (WARN_ON(!chanctx_conf)) {
		rcu_read_unlock();
		return;
	}
565
	chan = chanctx_conf->def.chan;
566
	rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
J
Johannes Berg 已提交
567 568
	rcu_read_unlock();
	sband = local->hw.wiphy->bands[chan->band];
569
	shift = ieee80211_vif_get_shift(&sdata->vif);
J
Johannes Berg 已提交
570 571 572 573 574 575 576 577

	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)...
		 */
578 579 580 581
		rates_len = ieee80211_parse_bitrates(&chanctx_conf->def, sband,
						     assoc_data->supp_rates,
						     assoc_data->supp_rates_len,
						     &rates);
J
Johannes Berg 已提交
582 583 584 585 586 587
	} else {
		/*
		 * In case AP not provide any supported rates information
		 * before association, we send information element(s) with
		 * all rates that we support.
		 */
588 589 590 591 592 593 594 595
		rates_len = 0;
		for (i = 0; i < sband->n_bitrates; i++) {
			if ((rate_flags & sband->bitrates[i].flags)
			    != rate_flags)
				continue;
			rates |= BIT(i);
			rates_len++;
		}
J
Johannes Berg 已提交
596 597 598 599 600 601 602 603 604
	}

	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 已提交
605
			2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
J
Johannes Berg 已提交
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
			assoc_data->ie_len + /* extra IEs */
			9, /* WMM */
			GFP_KERNEL);
	if (!skb)
		return;

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

	capab = WLAN_CAPABILITY_ESS;

	if (sband->band == IEEE80211_BAND_2GHZ) {
		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
			capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
			capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
	}

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

	if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
	    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
		capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
	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);

	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);
		mgmt->u.reassoc_req.listen_interval =
				cpu_to_le16(local->hw.conf.listen_interval);
		memcpy(mgmt->u.reassoc_req.current_ap, assoc_data->prev_bssid,
		       ETH_ALEN);
	} 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);
		mgmt->u.assoc_req.listen_interval =
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
	pos = skb_put(skb, 2 + assoc_data->ssid_len);
	*pos++ = WLAN_EID_SSID;
	*pos++ = assoc_data->ssid_len;
	memcpy(pos, assoc_data->ssid, assoc_data->ssid_len);

	/* 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) {
672 673 674
			int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
						5 * (1 << shift));
			*pos++ = (u8) rate;
J
Johannes Berg 已提交
675 676 677 678 679 680 681 682 683 684 685 686
			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) {
687 688 689 690
				int rate;
				rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
						    5 * (1 << shift));
				*pos++ = (u8) rate;
J
Johannes Berg 已提交
691 692 693 694 695 696 697 698 699 700
			}
		}
	}

	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
		/* 1. power capabilities */
		pos = skb_put(skb, 4);
		*pos++ = WLAN_EID_PWR_CAPABILITY;
		*pos++ = 2;
		*pos++ = 0; /* min tx power */
701 702
		 /* max tx power */
		*pos++ = ieee80211_chandef_max_power(&chanctx_conf->def);
J
Johannes Berg 已提交
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737

		/* 2. supported channels */
		/* 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*/
		}
	}

	/* if present, add any custom IEs that go before HT */
	if (assoc_data->ie_len && assoc_data->ie) {
		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,
			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
		};
		noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
					     before_ht, ARRAY_SIZE(before_ht),
					     offset);
		pos = skb_put(skb, noffset - offset);
		memcpy(pos, assoc_data->ie + offset, noffset - offset);
		offset = noffset;
	}

J
Johannes Berg 已提交
738 739 740 741
	if (WARN_ON_ONCE((ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
			 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)))
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;

742
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
743
		ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
744
				    sband, chan, sdata->smps_mode);
J
Johannes Berg 已提交
745

746
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
747 748
		ieee80211_add_vht_ie(sdata, skb, sband,
				     &assoc_data->ap_vht_cap);
749

J
Johannes Berg 已提交
750 751 752 753 754 755 756 757 758 759
	/* if present, add any custom non-vendor IEs that go after HT */
	if (assoc_data->ie_len && assoc_data->ie) {
		noffset = ieee80211_ie_split_vendor(assoc_data->ie,
						    assoc_data->ie_len,
						    offset);
		pos = skb_put(skb, noffset - offset);
		memcpy(pos, assoc_data->ie + offset, noffset - offset);
		offset = noffset;
	}

760 761
	if (assoc_data->wmm) {
		if (assoc_data->uapsd) {
762 763
			qos_info = ifmgd->uapsd_queues;
			qos_info |= (ifmgd->uapsd_max_sp_len <<
J
Johannes Berg 已提交
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
				     IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
		} else {
			qos_info = 0;
		}

		pos = skb_put(skb, 9);
		*pos++ = WLAN_EID_VENDOR_SPECIFIC;
		*pos++ = 7; /* len */
		*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
		*pos++ = 0x50;
		*pos++ = 0xf2;
		*pos++ = 2; /* WME */
		*pos++ = 0; /* WME info */
		*pos++ = 1; /* WME ver */
		*pos++ = qos_info;
	}

	/* add any remaining custom (i.e. vendor specific here) IEs */
	if (assoc_data->ie_len && assoc_data->ie) {
		noffset = assoc_data->ie_len;
		pos = skb_put(skb, noffset - offset);
		memcpy(pos, assoc_data->ie + offset, noffset - offset);
	}

J
Johannes Berg 已提交
788 789
	drv_mgd_prepare_tx(local, sdata);

J
Johannes Berg 已提交
790
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
791 792 793
	if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
						IEEE80211_TX_INTFL_MLME_CONN_TX;
J
Johannes Berg 已提交
794 795 796
	ieee80211_tx_skb(sdata, skb);
}

797 798 799 800 801 802
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_pspoll *pspoll;
	struct sk_buff *skb;

803 804
	skb = ieee80211_pspoll_get(&local->hw, &sdata->vif);
	if (!skb)
805 806
		return;

807 808
	pspoll = (struct ieee80211_pspoll *) skb->data;
	pspoll->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
809

810 811
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
	ieee80211_tx_skb(sdata, skb);
812 813
}

814 815 816 817 818
void ieee80211_send_nullfunc(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
			     int powersave)
{
	struct sk_buff *skb;
819
	struct ieee80211_hdr_3addr *nullfunc;
820
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
821

822 823
	skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif);
	if (!skb)
824 825
		return;

826
	nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
827
	if (powersave)
828
		nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
829

830 831
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
					IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
832 833 834 835

	if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;

836
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
837 838
		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE;

839
	ieee80211_tx_skb(sdata, skb);
840 841
}

842 843 844 845 846 847 848 849 850 851 852
static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
					  struct ieee80211_sub_if_data *sdata)
{
	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);
853
	if (!skb)
854
		return;
855

856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
	skb_reserve(skb, local->hw.extra_tx_headroom);

	nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30);
	memset(nullfunc, 0, 30);
	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);
}

872 873 874 875 876
/* 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);
877
	struct ieee80211_local *local = sdata->local;
878
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
879 880
	u32 changed = 0;
	int ret;
881

882
	if (!ieee80211_sdata_running(sdata))
883 884
		return;

885
	sdata_lock(sdata);
886 887
	if (!ifmgd->associated)
		goto out;
888

889 890 891 892 893 894 895 896 897
	ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
					   &changed);
	if (ret) {
		sdata_info(sdata,
			   "vif channel switch failed, disconnecting\n");
		ieee80211_queue_work(&sdata->local->hw,
				     &ifmgd->csa_connection_drop_work);
		goto out;
	}
898

899 900 901 902 903 904 905 906 907
	if (!local->use_chanctx) {
		local->_oper_chandef = local->csa_chandef;
		/* Call "hw_config" only if doing sw channel switch.
		 * Otherwise update the channel directly
		 */
		if (!local->ops->channel_switch)
			ieee80211_hw_config(local, 0);
		else
			local->hw.conf.chandef = local->_oper_chandef;
908
	}
909

910
	/* XXX: shouldn't really modify cfg80211-owned data! */
911
	ifmgd->associated->channel = local->csa_chandef.chan;
912

913
	/* XXX: wait for a beacon first? */
914
	ieee80211_wake_queues_by_reason(&local->hw,
915
					IEEE80211_MAX_QUEUE_MAP,
916
					IEEE80211_QUEUE_STOP_REASON_CSA);
917 918 919

	ieee80211_bss_info_change_notify(sdata, changed);

920
 out:
921
	sdata->vif.csa_active = false;
922
	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
923
	sdata_unlock(sdata);
924 925
}

926 927
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
{
J
Johannes Berg 已提交
928 929
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
930 931 932

	trace_api_chswitch_done(sdata, success);
	if (!success) {
933 934 935 936 937 938
		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);
939 940 941 942
	}
}
EXPORT_SYMBOL(ieee80211_chswitch_done);

943 944 945 946
static void ieee80211_chswitch_timer(unsigned long data)
{
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
947

948
	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
949 950
}

951
static void
J
Johannes Berg 已提交
952
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
953 954
				 u64 timestamp, struct ieee802_11_elems *elems,
				 bool beacon)
955
{
956
	struct ieee80211_local *local = sdata->local;
957
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
958
	struct cfg80211_bss *cbss = ifmgd->associated;
J
Johannes Berg 已提交
959
	struct ieee80211_chanctx *chanctx;
960
	enum ieee80211_band current_band;
961
	struct ieee80211_csa_ie csa_ie;
962
	int res;
963

964
	sdata_assert_lock(sdata);
965

966
	if (!cbss)
967 968
		return;

969
	if (local->scanning)
970 971
		return;

972
	/* disregard subsequent announcements if we are already processing */
973 974 975
	if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
		return;

976
	current_band = cbss->channel->band;
977
	memset(&csa_ie, 0, sizeof(csa_ie));
978 979
	res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
					   ifmgd->flags,
980
					   ifmgd->associated->bssid, &csa_ie);
981
	if (res	< 0)
982
		ieee80211_queue_work(&local->hw,
983
				     &ifmgd->csa_connection_drop_work);
984
	if (res)
985
		return;
986

987
	if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
988 989 990
				     IEEE80211_CHAN_DISABLED)) {
		sdata_info(sdata,
			   "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
991
			   ifmgd->associated->bssid,
992 993 994
			   csa_ie.chandef.chan->center_freq,
			   csa_ie.chandef.width, csa_ie.chandef.center_freq1,
			   csa_ie.chandef.center_freq2);
995 996 997 998 999
		ieee80211_queue_work(&local->hw,
				     &ifmgd->csa_connection_drop_work);
		return;
	}

1000
	ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
1001
	sdata->vif.csa_active = true;
1002

1003
	mutex_lock(&local->chanctx_mtx);
1004
	if (local->use_chanctx) {
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
		u32 num_chanctx = 0;
		list_for_each_entry(chanctx, &local->chanctx_list, list)
		       num_chanctx++;

		if (num_chanctx > 1 ||
		    !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
			sdata_info(sdata,
				   "not handling chan-switch with channel contexts\n");
			ieee80211_queue_work(&local->hw,
					     &ifmgd->csa_connection_drop_work);
			mutex_unlock(&local->chanctx_mtx);
			return;
		}
J
Johannes Berg 已提交
1018 1019 1020
	}

	if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) {
1021 1022
		ieee80211_queue_work(&local->hw,
				     &ifmgd->csa_connection_drop_work);
1023
		mutex_unlock(&local->chanctx_mtx);
J
Johannes Berg 已提交
1024 1025 1026 1027 1028 1029 1030
		return;
	}
	chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
			       struct ieee80211_chanctx, conf);
	if (chanctx->refcount > 1) {
		sdata_info(sdata,
			   "channel switch with multiple interfaces on the same channel, disconnecting\n");
1031
		ieee80211_queue_work(&local->hw,
J
Johannes Berg 已提交
1032
				     &ifmgd->csa_connection_drop_work);
1033
		mutex_unlock(&local->chanctx_mtx);
J
Johannes Berg 已提交
1034 1035
		return;
	}
1036
	mutex_unlock(&local->chanctx_mtx);
J
Johannes Berg 已提交
1037

1038
	local->csa_chandef = csa_ie.chandef;
J
Johannes Berg 已提交
1039

1040
	if (csa_ie.mode)
1041
		ieee80211_stop_queues_by_reason(&local->hw,
1042
				IEEE80211_MAX_QUEUE_MAP,
1043 1044
				IEEE80211_QUEUE_STOP_REASON_CSA);

1045
	if (local->ops->channel_switch) {
1046
		/* use driver's channel switch callback */
1047 1048
		struct ieee80211_channel_switch ch_switch = {
			.timestamp = timestamp,
1049 1050 1051
			.block_tx = csa_ie.mode,
			.chandef = csa_ie.chandef,
			.count = csa_ie.count,
1052 1053
		};

1054
		drv_channel_switch(local, &ch_switch);
1055 1056 1057 1058
		return;
	}

	/* channel switch handled in software */
1059
	if (csa_ie.count <= 1)
1060
		ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
1061
	else
1062
		mod_timer(&ifmgd->chswitch_timer,
1063
			  TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
1064 1065
}

1066 1067 1068 1069
static u32 ieee80211_handle_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)
1070
{
1071 1072 1073 1074
	struct ieee80211_country_ie_triplet *triplet;
	int chan = ieee80211_frequency_to_channel(channel->center_freq);
	int i, chan_pwr, chan_increment, new_ap_level;
	bool have_chan_pwr = false;
1075

1076 1077
	/* Invalid IE */
	if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
1078
		return 0;
1079

1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
	triplet = (void *)(country_ie + 3);
	country_ie_len -= 3;

	switch (channel->band) {
	default:
		WARN_ON_ONCE(1);
		/* fall through */
	case IEEE80211_BAND_2GHZ:
	case IEEE80211_BAND_60GHZ:
		chan_increment = 1;
		break;
	case IEEE80211_BAND_5GHZ:
		chan_increment = 4;
		break;
1094
	}
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118

	/* 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;
				chan_pwr = triplet->chans.max_power;
				break;
			}
		}
		if (have_chan_pwr)
			break;

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

	if (!have_chan_pwr)
1119
		return 0;
1120 1121 1122

	new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);

1123 1124
	if (sdata->ap_power_level == new_ap_level)
		return 0;
1125 1126 1127 1128 1129

	sdata_info(sdata,
		   "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
		   new_ap_level, chan_pwr, *pwr_constr_elem,
		   sdata->u.mgd.bssid);
1130 1131 1132 1133
	sdata->ap_power_level = new_ap_level;
	if (__ieee80211_recalc_txpower(sdata))
		return BSS_CHANGED_TXPOWER;
	return 0;
1134 1135
}

1136 1137 1138 1139 1140 1141
/* 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 已提交
1142 1143 1144 1145
	/*
	 * If we are scanning right now then the parameters will
	 * take effect when scan finishes.
	 */
1146
	if (local->scanning)
J
Johannes Berg 已提交
1147 1148
		return;

1149 1150 1151 1152 1153 1154 1155
	if (conf->dynamic_ps_timeout > 0 &&
	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
		mod_timer(&local->dynamic_ps_timer, jiffies +
			  msecs_to_jiffies(conf->dynamic_ps_timeout));
	} else {
		if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
			ieee80211_send_nullfunc(local, sdata, 1);
1156

1157 1158 1159 1160 1161 1162
		if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
		    (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
			return;

		conf->flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
	}
}

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);
	}
}

1180 1181 1182 1183
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 已提交
1184
	bool authorized = false;
1185 1186 1187 1188

	if (!mgd->powersave)
		return false;

1189 1190 1191
	if (mgd->broken_ap)
		return false;

1192 1193 1194
	if (!mgd->associated)
		return false;

1195
	if (mgd->flags & IEEE80211_STA_CONNECTION_POLL)
1196 1197
		return false;

1198
	if (!mgd->have_beacon)
1199 1200
		return false;

1201 1202 1203
	rcu_read_lock();
	sta = sta_info_get(sdata, mgd->bssid);
	if (sta)
J
Johannes Berg 已提交
1204
		authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
1205 1206
	rcu_read_unlock();

J
Johannes Berg 已提交
1207
	return authorized;
1208 1209
}

1210
/* need to hold RTNL or interface lock */
1211
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
1212 1213 1214
{
	struct ieee80211_sub_if_data *sdata, *found = NULL;
	int count = 0;
1215
	int timeout;
1216 1217 1218 1219 1220 1221 1222

	if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) {
		local->ps_sdata = NULL;
		return;
	}

	list_for_each_entry(sdata, &local->interfaces, list) {
1223
		if (!ieee80211_sdata_running(sdata))
1224
			continue;
1225 1226 1227 1228 1229 1230 1231 1232
		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;
		}
1233 1234 1235 1236 1237 1238
		if (sdata->vif.type != NL80211_IFTYPE_STATION)
			continue;
		found = sdata;
		count++;
	}

1239
	if (count == 1 && ieee80211_powersave_allowed(found)) {
1240 1241 1242
		s32 beaconint_us;

		if (latency < 0)
M
Mark Gross 已提交
1243
			latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
1244 1245 1246 1247

		beaconint_us = ieee80211_tu_to_usec(
					found->vif.bss_conf.beacon_int);

1248
		timeout = local->dynamic_ps_forced_timeout;
1249 1250
		if (timeout < 0) {
			/*
1251 1252
			 * Go to full PSM if the user configures a very low
			 * latency requirement.
1253 1254 1255
			 * The 2000 second value is there for compatibility
			 * until the PM_QOS_NETWORK_LATENCY is configured
			 * with real values.
1256
			 */
1257 1258
			if (latency > (1900 * USEC_PER_MSEC) &&
			    latency != (2000 * USEC_PER_SEC))
1259
				timeout = 0;
1260 1261
			else
				timeout = 100;
1262
		}
1263
		local->hw.conf.dynamic_ps_timeout = timeout;
1264

1265
		if (beaconint_us > latency) {
1266
			local->ps_sdata = NULL;
1267 1268
		} else {
			int maxslp = 1;
1269
			u8 dtimper = found->u.mgd.dtim_period;
1270 1271 1272 1273 1274

			/* If the TIM IE is invalid, pretend the value is 1 */
			if (!dtimper)
				dtimper = 1;
			else if (dtimper > 1)
1275 1276 1277
				maxslp = min_t(int, dtimper,
						    latency / beaconint_us);

1278
			local->hw.conf.max_sleep_period = maxslp;
1279
			local->hw.conf.ps_dtim_period = dtimper;
1280
			local->ps_sdata = found;
1281
		}
1282
	} else {
1283
		local->ps_sdata = NULL;
1284
	}
1285 1286 1287 1288

	ieee80211_change_ps(local);
}

E
Eliad Peller 已提交
1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
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);
	}
}

1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
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,
1311
					IEEE80211_MAX_QUEUE_MAP,
1312 1313 1314 1315 1316 1317 1318 1319 1320
					IEEE80211_QUEUE_STOP_REASON_PS);
}

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;
1321
	struct ieee80211_if_managed *ifmgd;
1322 1323
	unsigned long flags;
	int q;
1324 1325 1326 1327 1328

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

1329 1330
	ifmgd = &sdata->u.mgd;

1331 1332 1333
	if (local->hw.conf.flags & IEEE80211_CONF_PS)
		return;

1334
	if (local->hw.conf.dynamic_ps_timeout > 0) {
1335 1336
		/* don't enter PS if TX frames are pending */
		if (drv_tx_frames_pending(local)) {
1337 1338 1339 1340 1341
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(
				  local->hw.conf.dynamic_ps_timeout));
			return;
		}
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359

		/*
		 * 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);
1360 1361
	}

1362
	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
1363
	    !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
1364
		if (drv_tx_frames_pending(local)) {
1365 1366 1367
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(
				  local->hw.conf.dynamic_ps_timeout));
1368
		} else {
1369 1370
			ieee80211_send_nullfunc(local, sdata, 1);
			/* Flush to get the tx status of nullfunc frame */
1371
			ieee80211_flush_queues(local, sdata);
1372
		}
1373 1374
	}

1375 1376
	if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
	      (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) ||
1377 1378 1379 1380 1381
	    (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);
	}
1382 1383 1384 1385 1386 1387
}

void ieee80211_dynamic_ps_timer(unsigned long data)
{
	struct ieee80211_local *local = (void *) data;

1388
	if (local->quiescing || local->suspended)
1389 1390
		return;

1391
	ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
1392 1393
}

1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
void ieee80211_dfs_cac_timer_work(struct work_struct *work)
{
	struct delayed_work *delayed_work =
		container_of(work, struct delayed_work, work);
	struct ieee80211_sub_if_data *sdata =
		container_of(delayed_work, struct ieee80211_sub_if_data,
			     dfs_cac_timer_work);

	ieee80211_vif_release_channel(sdata);

	cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
}

J
Johannes Berg 已提交
1407
/* MLME */
1408
static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
1409
				     struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
1410
				     const u8 *wmm_param, size_t wmm_param_len)
1411 1412
{
	struct ieee80211_tx_queue_params params;
1413
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1414 1415
	size_t left;
	int count;
J
Johannes Berg 已提交
1416 1417
	const u8 *pos;
	u8 uapsd_queues = 0;
1418

1419
	if (!local->ops->conf_tx)
1420
		return false;
1421

J
Johannes Berg 已提交
1422
	if (local->hw.queues < IEEE80211_NUM_ACS)
1423
		return false;
1424 1425

	if (!wmm_param)
1426
		return false;
1427

1428
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
1429
		return false;
K
Kalle Valo 已提交
1430 1431

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

1434
	count = wmm_param[6] & 0x0f;
1435
	if (count == ifmgd->wmm_last_param_set)
1436
		return false;
1437
	ifmgd->wmm_last_param_set = count;
1438 1439 1440 1441 1442 1443

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

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

Y
Yoni Divinsky 已提交
1444
	sdata->wmm_acm = 0;
1445 1446 1447
	for (; left >= 4; left -= 4, pos += 4) {
		int aci = (pos[0] >> 5) & 0x03;
		int acm = (pos[0] >> 4) & 0x01;
K
Kalle Valo 已提交
1448
		bool uapsd = false;
1449 1450 1451
		int queue;

		switch (aci) {
1452
		case 1: /* AC_BK */
J
Johannes Berg 已提交
1453
			queue = 3;
J
Johannes Berg 已提交
1454
			if (acm)
Y
Yoni Divinsky 已提交
1455
				sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
K
Kalle Valo 已提交
1456 1457
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
				uapsd = true;
1458
			break;
1459
		case 2: /* AC_VI */
J
Johannes Berg 已提交
1460
			queue = 1;
J
Johannes Berg 已提交
1461
			if (acm)
Y
Yoni Divinsky 已提交
1462
				sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
K
Kalle Valo 已提交
1463 1464
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
				uapsd = true;
1465
			break;
1466
		case 3: /* AC_VO */
J
Johannes Berg 已提交
1467
			queue = 0;
J
Johannes Berg 已提交
1468
			if (acm)
Y
Yoni Divinsky 已提交
1469
				sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
K
Kalle Valo 已提交
1470 1471
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
				uapsd = true;
1472
			break;
1473
		case 0: /* AC_BE */
1474
		default:
J
Johannes Berg 已提交
1475
			queue = 2;
J
Johannes Berg 已提交
1476
			if (acm)
Y
Yoni Divinsky 已提交
1477
				sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
K
Kalle Valo 已提交
1478 1479
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
				uapsd = true;
1480 1481 1482 1483 1484 1485
			break;
		}

		params.aifs = pos[0] & 0x0f;
		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params.cw_min = ecw2cw(pos[1] & 0x0f);
1486
		params.txop = get_unaligned_le16(pos + 2);
1487
		params.acm = acm;
K
Kalle Valo 已提交
1488 1489
		params.uapsd = uapsd;

J
Johannes Berg 已提交
1490 1491 1492 1493 1494
		mlme_dbg(sdata,
			 "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
			 queue, aci, acm,
			 params.aifs, params.cw_min, params.cw_max,
			 params.txop, params.uapsd);
1495 1496
		sdata->tx_conf[queue] = params;
		if (drv_conf_tx(local, sdata, queue, &params))
J
Johannes Berg 已提交
1497 1498 1499
			sdata_err(sdata,
				  "failed to set TX queue parameters for queue %d\n",
				  queue);
1500
	}
1501 1502

	/* enable WMM or activate new settings */
1503
	sdata->vif.bss_conf.qos = true;
1504
	return true;
1505 1506
}

1507 1508 1509 1510
static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)
{
	lockdep_assert_held(&sdata->local->mtx);

1511
	sdata->u.mgd.flags &= ~IEEE80211_STA_CONNECTION_POLL;
1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
	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 已提交
1522 1523
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
1524
{
J
Johannes Berg 已提交
1525
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1526
	u32 changed = 0;
J
Johannes Berg 已提交
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
	bool use_protection;
	bool use_short_preamble;
	bool use_short_slot;

	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);
J
Johannes Berg 已提交
1540
	if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_5GHZ)
1541
		use_short_slot = true;
1542

1543 1544 1545
	if (use_protection != bss_conf->use_cts_prot) {
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
1546
	}
1547

1548 1549
	if (use_short_preamble != bss_conf->use_short_preamble) {
		bss_conf->use_short_preamble = use_short_preamble;
1550
		changed |= BSS_CHANGED_ERP_PREAMBLE;
1551
	}
1552

J
Johannes Berg 已提交
1553 1554 1555
	if (use_short_slot != bss_conf->use_short_slot) {
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
1556 1557 1558 1559 1560
	}

	return changed;
}

1561
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1562
				     struct cfg80211_bss *cbss,
J
Johannes Berg 已提交
1563
				     u32 bss_info_changed)
1564
{
1565
	struct ieee80211_bss *bss = (void *)cbss->priv;
1566
	struct ieee80211_local *local = sdata->local;
1567
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1568

J
Johannes Berg 已提交
1569
	bss_info_changed |= BSS_CHANGED_ASSOC;
1570
	bss_info_changed |= ieee80211_handle_bss_capability(sdata,
1571
		bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
1572

1573
	sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
1574
		beacon_loss_count * bss_conf->beacon_int));
1575

1576 1577
	sdata->u.mgd.associated = cbss;
	memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
1578

1579 1580
	sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;

1581
	if (sdata->vif.p2p) {
1582
		const struct cfg80211_bss_ies *ies;
1583

1584 1585 1586 1587 1588 1589 1590 1591
		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 已提交
1592 1593
					(u8 *) &bss_conf->p2p_noa_attr,
					sizeof(bss_conf->p2p_noa_attr));
1594
			if (ret >= 2) {
J
Janusz Dziedzic 已提交
1595 1596
				sdata->u.mgd.p2p_noa_index =
					bss_conf->p2p_noa_attr.index;
1597 1598
				bss_info_changed |= BSS_CHANGED_P2P_PS;
			}
1599
		}
1600
		rcu_read_unlock();
1601 1602
	}

J
Johannes Berg 已提交
1603
	/* just to be sure */
1604
	ieee80211_stop_poll(sdata);
J
Johannes Berg 已提交
1605

1606
	ieee80211_led_assoc(local, 1);
1607

1608
	if (sdata->u.mgd.have_beacon) {
1609 1610 1611 1612 1613 1614 1615
		/*
		 * 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;
1616
		bss_conf->beacon_rate = bss->beacon_rate;
1617
		bss_info_changed |= BSS_CHANGED_BEACON_INFO;
1618
	} else {
1619
		bss_conf->beacon_rate = NULL;
1620
		bss_conf->dtim_period = 0;
1621
	}
1622

1623
	bss_conf->assoc = 1;
1624

1625
	/* Tell the driver to monitor connection quality (if supported) */
1626
	if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI &&
1627
	    bss_conf->cqm_rssi_thold)
1628 1629
		bss_info_changed |= BSS_CHANGED_CQM;

1630
	/* Enable ARP filtering */
1631
	if (bss_conf->arp_addr_cnt)
1632 1633
		bss_info_changed |= BSS_CHANGED_ARP_FILTER;

J
Johannes Berg 已提交
1634
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
1635

J
Johannes Berg 已提交
1636 1637 1638
	mutex_lock(&local->iflist_mtx);
	ieee80211_recalc_ps(local, -1);
	mutex_unlock(&local->iflist_mtx);
1639

1640
	ieee80211_recalc_smps(sdata);
E
Eliad Peller 已提交
1641 1642
	ieee80211_recalc_ps_vif(sdata);

1643
	netif_carrier_on(sdata->dev);
1644 1645
}

1646
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1647 1648
				   u16 stype, u16 reason, bool tx,
				   u8 *frame_buf)
1649
{
1650
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1651
	struct ieee80211_local *local = sdata->local;
1652
	u32 changed = 0;
1653

1654
	sdata_assert_lock(sdata);
1655

1656 1657 1658
	if (WARN_ON_ONCE(tx && !frame_buf))
		return;

J
Johannes Berg 已提交
1659 1660 1661
	if (WARN_ON(!ifmgd->associated))
		return;

1662 1663
	ieee80211_stop_poll(sdata);

1664
	ifmgd->associated = NULL;
1665 1666
	netif_carrier_off(sdata->dev);

1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677
	/*
	 * 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 已提交
1678 1679 1680
	/* disable per-vif ps */
	ieee80211_recalc_ps_vif(sdata);

1681 1682
	/* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
	if (tx)
1683
		ieee80211_flush_queues(local, sdata);
1684

1685 1686
	/* deauthenticate/disassociate now */
	if (tx || frame_buf)
1687 1688
		ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
					       reason, tx, frame_buf);
1689 1690 1691

	/* flush out frame */
	if (tx)
1692
		ieee80211_flush_queues(local, sdata);
1693

1694 1695 1696
	/* clear bssid only after building the needed mgmt frames */
	memset(ifmgd->bssid, 0, ETH_ALEN);

1697
	/* remove AP and TDLS peers */
1698
	sta_info_flush_defer(sdata);
1699 1700

	/* finally reset all BSS / config parameters */
1701 1702 1703
	changed |= ieee80211_reset_erp_info(sdata);

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

J
Janusz Dziedzic 已提交
1707 1708 1709
	ifmgd->p2p_noa_index = -1;
	memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
	       sizeof(sdata->vif.bss_conf.p2p_noa_attr));
1710

1711
	/* on the next assoc, re-program HT/VHT parameters */
B
Ben Greear 已提交
1712 1713
	memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
	memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1714 1715
	memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
	memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
1716

1717
	sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
1718

1719 1720 1721
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

1722
	/* Disable ARP filtering */
1723
	if (sdata->vif.bss_conf.arp_addr_cnt)
1724 1725
		changed |= BSS_CHANGED_ARP_FILTER;

1726 1727 1728
	sdata->vif.bss_conf.qos = false;
	changed |= BSS_CHANGED_QOS;

1729 1730
	/* The BSSID (not really interesting) and HT changed */
	changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
J
Johannes Berg 已提交
1731
	ieee80211_bss_info_change_notify(sdata, changed);
1732

1733 1734 1735
	/* disassociated - set to defaults now */
	ieee80211_set_wmm_default(sdata, false);

1736 1737 1738 1739
	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);
1740

1741
	sdata->vif.bss_conf.dtim_period = 0;
1742 1743
	sdata->vif.bss_conf.beacon_rate = NULL;

1744
	ifmgd->have_beacon = false;
1745

1746 1747
	ifmgd->flags = 0;
	ieee80211_vif_release_channel(sdata);
1748
}
1749

1750 1751 1752 1753 1754 1755 1756 1757
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_hdr *hdr)
{
	/*
	 * We can postpone the mgd.timer whenever receiving unicast frames
	 * from AP because we know that the connection is working both ways
	 * at that time. But multicast frames (and hence also beacons) must
	 * be ignored here, because we need to trigger the timer during
J
Johannes Berg 已提交
1758 1759
	 * data idle periods for sending the periodic probe request to the
	 * AP we're connected to.
1760
	 */
J
Johannes Berg 已提交
1761 1762 1763
	if (is_multicast_ether_addr(hdr->addr1))
		return;

1764
	ieee80211_sta_reset_conn_monitor(sdata);
1765
}
1766

1767 1768 1769
static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1770
	struct ieee80211_local *local = sdata->local;
1771

1772
	mutex_lock(&local->mtx);
1773 1774
	if (!(ifmgd->flags & IEEE80211_STA_CONNECTION_POLL))
		goto out;
1775

1776
	__ieee80211_stop_poll(sdata);
1777 1778 1779 1780

	mutex_lock(&local->iflist_mtx);
	ieee80211_recalc_ps(local, -1);
	mutex_unlock(&local->iflist_mtx);
1781 1782

	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1783
		goto out;
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794

	/*
	 * 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));
1795 1796
out:
	mutex_unlock(&local->mtx);
1797 1798 1799
}

void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1800
			     struct ieee80211_hdr *hdr, bool ack)
1801
{
F
Felix Fietkau 已提交
1802
	if (!ieee80211_is_data(hdr->frame_control))
1803 1804 1805 1806
	    return;

	if (ieee80211_is_nullfunc(hdr->frame_control) &&
	    sdata->u.mgd.probe_send_count > 0) {
1807
		if (ack)
1808
			ieee80211_sta_reset_conn_monitor(sdata);
1809 1810
		else
			sdata->u.mgd.nullfunc_failed = true;
1811
		ieee80211_queue_work(&sdata->local->hw, &sdata->work);
1812
		return;
1813
	}
1814 1815 1816

	if (ack)
		ieee80211_sta_reset_conn_monitor(sdata);
1817 1818
}

1819 1820 1821 1822
static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	const u8 *ssid;
1823
	u8 *dst = ifmgd->associated->bssid;
1824
	u8 unicast_limit = max(1, max_probe_tries - 3);
1825 1826 1827 1828 1829 1830 1831 1832

	/*
	 * 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;
1833

1834 1835 1836 1837 1838 1839 1840
	/*
	 * 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.
	 */
1841 1842
	ifmgd->probe_send_count++;

1843 1844
	if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
		ifmgd->nullfunc_failed = false;
1845
		ieee80211_send_nullfunc(sdata->local, sdata, 0);
1846
	} else {
1847 1848
		int ssid_len;

1849
		rcu_read_lock();
1850
		ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1851 1852 1853 1854 1855 1856
		if (WARN_ON_ONCE(ssid == NULL))
			ssid_len = 0;
		else
			ssid_len = ssid[1];

		ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
1857
					 0, (u32) -1, true, 0,
J
Johannes Berg 已提交
1858
					 ifmgd->associated->channel, false);
1859
		rcu_read_unlock();
1860
	}
1861

1862
	ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
1863
	run_again(sdata, ifmgd->probe_timeout);
1864
	if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
1865
		ieee80211_flush_queues(sdata->local, sdata);
1866 1867
}

J
Johannes Berg 已提交
1868 1869
static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
				   bool beacon)
1870 1871
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1872
	bool already = false;
1873

1874
	if (!ieee80211_sdata_running(sdata))
1875 1876
		return;

1877
	sdata_lock(sdata);
1878 1879 1880 1881

	if (!ifmgd->associated)
		goto out;

1882 1883 1884 1885 1886 1887 1888
	mutex_lock(&sdata->local->mtx);

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

1889
	if (beacon) {
J
Johannes Berg 已提交
1890
		mlme_dbg_ratelimited(sdata,
1891 1892
				     "detected beacon loss from AP (missed %d beacons) - probing\n",
				     beacon_loss_count);
J
Johannes Berg 已提交
1893

1894 1895 1896 1897
		ieee80211_cqm_rssi_notify(&sdata->vif,
					  NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
					  GFP_KERNEL);
	}
1898

J
Johannes Berg 已提交
1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909
	/*
	 * 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!
	 */
1910
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
J
Johannes Berg 已提交
1911 1912
		already = true;

1913 1914
	mutex_unlock(&sdata->local->mtx);

J
Johannes Berg 已提交
1915 1916 1917
	if (already)
		goto out;

1918 1919 1920 1921
	mutex_lock(&sdata->local->iflist_mtx);
	ieee80211_recalc_ps(sdata->local, -1);
	mutex_unlock(&sdata->local->iflist_mtx);

1922 1923
	ifmgd->probe_send_count = 0;
	ieee80211_mgd_probe_ap_send(sdata);
1924
 out:
1925
	sdata_unlock(sdata);
1926 1927
}

1928 1929 1930 1931 1932
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;
1933
	struct cfg80211_bss *cbss;
1934 1935
	struct sk_buff *skb;
	const u8 *ssid;
1936
	int ssid_len;
1937 1938 1939 1940

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

1941
	sdata_assert_lock(sdata);
1942

1943 1944 1945 1946 1947 1948 1949
	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
1950 1951
		return NULL;

1952
	rcu_read_lock();
1953
	ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
1954 1955 1956 1957 1958
	if (WARN_ON_ONCE(ssid == NULL))
		ssid_len = 0;
	else
		ssid_len = ssid[1];

1959
	skb = ieee80211_build_probe_req(sdata, cbss->bssid,
J
Johannes Berg 已提交
1960
					(u32) -1, cbss->channel,
1961
					ssid + 2, ssid_len,
1962
					NULL, 0, true);
1963
	rcu_read_unlock();
1964 1965 1966 1967 1968

	return skb;
}
EXPORT_SYMBOL(ieee80211_ap_probereq_get);

1969
static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
1970 1971
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1972
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
1973

1974
	sdata_lock(sdata);
1975
	if (!ifmgd->associated) {
1976
		sdata_unlock(sdata);
1977 1978 1979
		return;
	}

1980 1981
	ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
			       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1982
			       true, frame_buf);
1983
	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
1984
	sdata->vif.csa_active = false;
1985
	ieee80211_wake_queues_by_reason(&sdata->local->hw,
1986
					IEEE80211_MAX_QUEUE_MAP,
1987
					IEEE80211_QUEUE_STOP_REASON_CSA);
1988

1989 1990
	cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
			      IEEE80211_DEAUTH_FRAME_LEN);
1991
	sdata_unlock(sdata);
1992 1993
}

1994
static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
J
Johannes Berg 已提交
1995 1996 1997
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data,
1998
			     u.mgd.beacon_connection_loss_work);
1999 2000 2001 2002
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct sta_info *sta;

	if (ifmgd->associated) {
2003
		rcu_read_lock();
2004 2005 2006
		sta = sta_info_get(sdata, ifmgd->bssid);
		if (sta)
			sta->beacon_loss_count++;
2007
		rcu_read_unlock();
2008
	}
J
Johannes Berg 已提交
2009

2010
	if (ifmgd->connection_loss) {
2011 2012
		sdata_info(sdata, "Connection to AP %pM lost\n",
			   ifmgd->bssid);
2013
		__ieee80211_disconnect(sdata);
2014
	} else {
2015
		ieee80211_mgd_probe_ap(sdata, true);
2016 2017 2018 2019 2020 2021 2022 2023 2024
	}
}

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);

2025
	__ieee80211_disconnect(sdata);
J
Johannes Berg 已提交
2026 2027
}

2028 2029 2030
void ieee80211_beacon_loss(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2031
	struct ieee80211_hw *hw = &sdata->local->hw;
2032

J
Johannes Berg 已提交
2033 2034
	trace_api_beacon_loss(sdata);

2035
	sdata->u.mgd.connection_loss = false;
2036
	ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
2037 2038 2039
}
EXPORT_SYMBOL(ieee80211_beacon_loss);

2040 2041 2042 2043 2044
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 已提交
2045 2046
	trace_api_connection_loss(sdata);

2047
	sdata->u.mgd.connection_loss = true;
2048 2049 2050 2051 2052
	ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
}
EXPORT_SYMBOL(ieee80211_connection_loss);


J
Johannes Berg 已提交
2053 2054 2055 2056 2057
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;

2058
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
2059 2060 2061 2062 2063 2064

	if (!assoc) {
		sta_info_destroy_addr(sdata, auth_data->bss->bssid);

		memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2065
		sdata->u.mgd.flags = 0;
J
Johannes Berg 已提交
2066
		ieee80211_vif_release_channel(sdata);
J
Johannes Berg 已提交
2067 2068
	}

2069
	cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
J
Johannes Berg 已提交
2070 2071 2072 2073 2074 2075 2076
	kfree(auth_data);
	sdata->u.mgd.auth_data = NULL;
}

static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_mgmt *mgmt, size_t len)
{
2077
	struct ieee80211_local *local = sdata->local;
J
Johannes Berg 已提交
2078 2079 2080
	struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
	u8 *pos;
	struct ieee802_11_elems elems;
2081
	u32 tx_flags = 0;
J
Johannes Berg 已提交
2082 2083

	pos = mgmt->u.auth.variable;
2084
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
J
Johannes Berg 已提交
2085 2086 2087
	if (!elems.challenge)
		return;
	auth_data->expected_transaction = 4;
J
Johannes Berg 已提交
2088
	drv_mgd_prepare_tx(sdata->local, sdata);
2089 2090 2091
	if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
		tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
			   IEEE80211_TX_INTFL_MLME_CONN_TX;
2092
	ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0,
J
Johannes Berg 已提交
2093 2094 2095
			    elems.challenge - 2, elems.challenge_len + 2,
			    auth_data->bss->bssid, auth_data->bss->bssid,
			    auth_data->key, auth_data->key_len,
2096
			    auth_data->key_idx, tx_flags);
J
Johannes Berg 已提交
2097 2098
}

2099 2100
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_mgmt *mgmt, size_t len)
J
Johannes Berg 已提交
2101 2102 2103 2104 2105 2106
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	u8 bssid[ETH_ALEN];
	u16 auth_alg, auth_transaction, status_code;
	struct sta_info *sta;

2107
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
2108 2109

	if (len < 24 + 6)
2110
		return;
J
Johannes Berg 已提交
2111 2112

	if (!ifmgd->auth_data || ifmgd->auth_data->done)
2113
		return;
J
Johannes Berg 已提交
2114 2115 2116

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

2117
	if (!ether_addr_equal(bssid, mgmt->bssid))
2118
		return;
J
Johannes Berg 已提交
2119 2120 2121 2122 2123 2124

	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 ||
2125 2126 2127 2128 2129
	    auth_transaction != ifmgd->auth_data->expected_transaction) {
		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);
2130
		return;
2131
	}
J
Johannes Berg 已提交
2132 2133

	if (status_code != WLAN_STATUS_SUCCESS) {
J
Johannes Berg 已提交
2134 2135
		sdata_info(sdata, "%pM denied authentication (status %d)\n",
			   mgmt->sa, status_code);
2136
		ieee80211_destroy_auth_data(sdata, false);
2137
		cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2138
		return;
J
Johannes Berg 已提交
2139 2140 2141 2142 2143 2144
	}

	switch (ifmgd->auth_data->algorithm) {
	case WLAN_AUTH_OPEN:
	case WLAN_AUTH_LEAP:
	case WLAN_AUTH_FT:
2145
	case WLAN_AUTH_SAE:
J
Johannes Berg 已提交
2146 2147 2148 2149 2150
		break;
	case WLAN_AUTH_SHARED_KEY:
		if (ifmgd->auth_data->expected_transaction != 4) {
			ieee80211_auth_challenge(sdata, mgmt, len);
			/* need another frame */
2151
			return;
J
Johannes Berg 已提交
2152 2153 2154 2155 2156
		}
		break;
	default:
		WARN_ONCE(1, "invalid auth alg %d",
			  ifmgd->auth_data->algorithm);
2157
		return;
J
Johannes Berg 已提交
2158 2159
	}

J
Johannes Berg 已提交
2160
	sdata_info(sdata, "authenticated\n");
J
Johannes Berg 已提交
2161 2162
	ifmgd->auth_data->done = true;
	ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
2163
	ifmgd->auth_data->timeout_started = true;
2164
	run_again(sdata, ifmgd->auth_data->timeout);
J
Johannes Berg 已提交
2165

2166 2167 2168 2169 2170 2171
	if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
	    ifmgd->auth_data->expected_transaction != 2) {
		/*
		 * Report auth frame to user space for processing since another
		 * round of Authentication frames is still needed.
		 */
2172
		cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2173
		return;
2174 2175
	}

J
Johannes Berg 已提交
2176 2177 2178 2179 2180 2181 2182 2183
	/* 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);
		goto out_err;
	}
	if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) {
J
Johannes Berg 已提交
2184
		sdata_info(sdata, "failed moving %pM to auth\n", bssid);
J
Johannes Berg 已提交
2185 2186 2187 2188
		goto out_err;
	}
	mutex_unlock(&sdata->local->sta_mtx);

2189
	cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2190
	return;
J
Johannes Berg 已提交
2191 2192 2193 2194 2195 2196
 out_err:
	mutex_unlock(&sdata->local->sta_mtx);
	/* ignore frame -- wait for timeout */
}


2197 2198
static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_mgmt *mgmt, size_t len)
2199
{
2200
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2201
	const u8 *bssid = NULL;
2202 2203
	u16 reason_code;

2204
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
2205

2206
	if (len < 24 + 2)
2207
		return;
2208

J
Johannes Berg 已提交
2209
	if (!ifmgd->associated ||
2210
	    !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
2211
		return;
2212

2213
	bssid = ifmgd->associated->bssid;
2214 2215 2216

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

J
Johannes Berg 已提交
2217 2218
	sdata_info(sdata, "deauthenticated from %pM (Reason: %u)\n",
		   bssid, reason_code);
2219

2220 2221
	ieee80211_set_disassoc(sdata, 0, 0, false, NULL);

2222
	cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2223 2224 2225
}


2226 2227
static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
				       struct ieee80211_mgmt *mgmt, size_t len)
2228
{
2229
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2230 2231
	u16 reason_code;

2232
	sdata_assert_lock(sdata);
2233

J
Johannes Berg 已提交
2234
	if (len < 24 + 2)
2235
		return;
2236

J
Johannes Berg 已提交
2237
	if (!ifmgd->associated ||
2238
	    !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
2239
		return;
2240 2241 2242

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

J
Johannes Berg 已提交
2243 2244
	sdata_info(sdata, "disassociated from %pM (Reason: %u)\n",
		   mgmt->sa, reason_code);
2245

2246 2247
	ieee80211_set_disassoc(sdata, 0, 0, false, NULL);

2248
	cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2249 2250
}

2251 2252 2253 2254
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,
2255 2256
				int *min_rate, int *min_rate_index,
				int shift, u32 rate_flags)
2257 2258 2259 2260
{
	int i, j;

	for (i = 0; i < supp_rates_len; i++) {
2261
		int rate = supp_rates[i] & 0x7f;
2262 2263
		bool is_basic = !!(supp_rates[i] & 0x80);

2264
		if ((rate * 5 * (1 << shift)) > 110)
2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279
			*have_higher_than_11mbit = true;

		/*
		 * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009
		 * 7.3.2.2 as a magic value instead of a rate. Hence, skip it.
		 *
		 * Note: Even through the membership selector and the basic
		 *	 rate flag share the same bit, they are not exactly
		 *	 the same.
		 */
		if (!!(supp_rates[i] & 0x80) &&
		    (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
			continue;

		for (j = 0; j < sband->n_bitrates; j++) {
2280 2281 2282 2283 2284 2285 2286 2287 2288
			struct ieee80211_rate *br;
			int brate;

			br = &sband->bitrates[j];
			if ((rate_flags & br->flags) != rate_flags)
				continue;

			brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
			if (brate == rate) {
2289 2290 2291
				*rates |= BIT(j);
				if (is_basic)
					*basic_rates |= BIT(j);
2292 2293
				if ((rate * 5) < *min_rate) {
					*min_rate = rate * 5;
2294 2295 2296 2297 2298 2299 2300
					*min_rate_index = j;
				}
				break;
			}
		}
	}
}
2301

J
Johannes Berg 已提交
2302 2303 2304 2305 2306
static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
					 bool assoc)
{
	struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;

2307
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
2308 2309 2310 2311 2312 2313

	if (!assoc) {
		sta_info_destroy_addr(sdata, assoc_data->bss->bssid);

		memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2314
		sdata->u.mgd.flags = 0;
J
Johannes Berg 已提交
2315
		ieee80211_vif_release_channel(sdata);
J
Johannes Berg 已提交
2316 2317 2318 2319 2320 2321 2322 2323
	}

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

static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
				    struct cfg80211_bss *cbss,
J
Johannes Berg 已提交
2324
				    struct ieee80211_mgmt *mgmt, size_t len)
2325
{
2326
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2327
	struct ieee80211_local *local = sdata->local;
2328
	struct ieee80211_supported_band *sband;
2329
	struct sta_info *sta;
J
Johannes Berg 已提交
2330 2331
	u8 *pos;
	u16 capab_info, aid;
2332
	struct ieee802_11_elems elems;
J
Johannes Berg 已提交
2333
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
2334 2335
	const struct cfg80211_bss_ies *bss_ies = NULL;
	struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
J
Johannes Berg 已提交
2336
	u32 changed = 0;
2337
	int err;
2338
	bool ret;
2339

J
Johannes Berg 已提交
2340
	/* AssocResp and ReassocResp have identical structure */
2341 2342

	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
J
Johannes Berg 已提交
2343
	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
2344

2345
	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
J
Johannes Berg 已提交
2346 2347
		sdata_info(sdata, "invalid AID value 0x%x; bits 15:14 not set\n",
			   aid);
2348 2349
	aid &= ~(BIT(15) | BIT(14));

2350 2351 2352
	ifmgd->broken_ap = false;

	if (aid == 0 || aid > IEEE80211_MAX_AID) {
J
Johannes Berg 已提交
2353 2354
		sdata_info(sdata, "invalid AID value %d (out of range), turn off PS\n",
			   aid);
2355 2356 2357 2358
		aid = 0;
		ifmgd->broken_ap = true;
	}

J
Johannes Berg 已提交
2359
	pos = mgmt->u.assoc_resp.variable;
2360
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
J
Johannes Berg 已提交
2361

2362
	if (!elems.supp_rates) {
J
Johannes Berg 已提交
2363
		sdata_info(sdata, "no SuppRates element in AssocResp\n");
J
Johannes Berg 已提交
2364
		return false;
2365 2366
	}

2367
	ifmgd->aid = aid;
2368

2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431
	/*
	 * 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.
	 */
	if ((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))) {
		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,
				       false, &bss_elems);
		if (assoc_data->wmm &&
		    !elems.wmm_param && bss_elems.wmm_param) {
			elems.wmm_param = bss_elems.wmm_param;
			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.
		 */
		if (!elems.ht_cap_elem && bss_elems.ht_cap_elem &&
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
			elems.ht_cap_elem = bss_elems.ht_cap_elem;
			sdata_info(sdata,
				   "AP bug: HT capability missing from AssocResp\n");
		}
		if (!elems.ht_operation && bss_elems.ht_operation &&
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
			elems.ht_operation = bss_elems.ht_operation;
			sdata_info(sdata,
				   "AP bug: HT operation missing from AssocResp\n");
		}
		if (!elems.vht_cap_elem && bss_elems.vht_cap_elem &&
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
			elems.vht_cap_elem = bss_elems.vht_cap_elem;
			sdata_info(sdata,
				   "AP bug: VHT capa missing from AssocResp\n");
		}
		if (!elems.vht_operation && bss_elems.vht_operation &&
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
			elems.vht_operation = bss_elems.vht_operation;
			sdata_info(sdata,
				   "AP bug: VHT operation missing from AssocResp\n");
		}
	}

2432 2433 2434 2435 2436 2437 2438
	/*
	 * We previously checked these in the beacon/probe response, so
	 * they should be present here. This is just a safety net.
	 */
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
	    (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
		sdata_info(sdata,
2439 2440 2441
			   "HT AP is missing WMM params or HT capability/operation\n");
		ret = false;
		goto out;
2442 2443 2444 2445 2446
	}

	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
	    (!elems.vht_cap_elem || !elems.vht_operation)) {
		sdata_info(sdata,
2447 2448 2449
			   "VHT AP is missing VHT capability/operation\n");
		ret = false;
		goto out;
2450 2451
	}

2452 2453 2454 2455 2456
	mutex_lock(&sdata->local->sta_mtx);
	/*
	 * station info was already allocated and inserted before
	 * the association and should be available to us
	 */
2457
	sta = sta_info_get(sdata, cbss->bssid);
2458 2459
	if (WARN_ON(!sta)) {
		mutex_unlock(&sdata->local->sta_mtx);
2460 2461
		ret = false;
		goto out;
2462
	}
2463

J
Johannes Berg 已提交
2464
	sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
2465

2466
	/* Set up internal HT/VHT capabilities */
2467
	if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
B
Ben Greear 已提交
2468
		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
2469
						  elems.ht_cap_elem, sta);
2470

M
Mahesh Palivela 已提交
2471 2472
	if (elems.vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
2473
						    elems.vht_cap_elem, sta);
M
Mahesh Palivela 已提交
2474

2475 2476 2477 2478 2479 2480
	/*
	 * 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.
	 */
2481

2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496
	/*
	 * 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.
	 */
	if (elems.opmode_notif &&
	    !(*elems.opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)) {
		u8 nss;

		nss = *elems.opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK;
		nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
		nss += 1;
		sta->sta.rx_nss = nss;
	}

2497
	rate_control_rate_init(sta);
2498

2499
	if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
J
Johannes Berg 已提交
2500
		set_sta_flag(sta, WLAN_STA_MFP);
2501

2502
	if (elems.wmm_param)
J
Johannes Berg 已提交
2503
		set_sta_flag(sta, WLAN_STA_WME);
2504

2505
	err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
2506 2507 2508
	if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
		err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
	if (err) {
J
Johannes Berg 已提交
2509 2510 2511
		sdata_info(sdata,
			   "failed to move station %pM to desired state\n",
			   sta->sta.addr);
2512 2513
		WARN_ON(__sta_info_destroy(sta));
		mutex_unlock(&sdata->local->sta_mtx);
2514 2515
		ret = false;
		goto out;
2516 2517
	}

2518
	mutex_unlock(&sdata->local->sta_mtx);
2519

2520 2521 2522 2523 2524 2525 2526 2527
	/*
	 * 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;

2528
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && elems.wmm_param)
2529
		ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
J
Johannes Berg 已提交
2530
					 elems.wmm_param_len);
2531
	else
2532 2533
		ieee80211_set_wmm_default(sdata, false);
	changed |= BSS_CHANGED_QOS;
2534

J
Johannes Berg 已提交
2535 2536 2537 2538
	/* set AID and assoc capability,
	 * ieee80211_set_associated() will tell the driver */
	bss_conf->aid = aid;
	bss_conf->assoc_capability = capab_info;
2539
	ieee80211_set_associated(sdata, cbss, changed);
2540

2541 2542 2543 2544 2545 2546 2547
	/*
	 * 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);

2548
	/*
J
Johannes Berg 已提交
2549 2550
	 * Start timer to probe the connection to the AP now.
	 * Also start the timer that will detect beacon loss.
2551
	 */
J
Johannes Berg 已提交
2552
	ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
2553
	ieee80211_sta_reset_beacon_monitor(sdata);
2554

2555 2556 2557 2558
	ret = true;
 out:
	kfree(bss_ies);
	return ret;
2559 2560
}

2561 2562 2563
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
					 struct ieee80211_mgmt *mgmt,
					 size_t len)
J
Johannes Berg 已提交
2564 2565 2566 2567 2568 2569 2570
{
	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;
	u8 *pos;
	bool reassoc;
2571
	struct cfg80211_bss *bss;
J
Johannes Berg 已提交
2572

2573
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
2574 2575

	if (!assoc_data)
2576
		return;
2577
	if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid))
2578
		return;
J
Johannes Berg 已提交
2579 2580 2581 2582 2583 2584 2585

	/*
	 * AssocResp and ReassocResp have identical structure, so process both
	 * of them in this function.
	 */

	if (len < 24 + 6)
2586
		return;
J
Johannes Berg 已提交
2587 2588 2589 2590 2591 2592

	reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);
	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);

J
Johannes Berg 已提交
2593 2594 2595 2596
	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 已提交
2597 2598

	pos = mgmt->u.assoc_resp.variable;
2599
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
J
Johannes Berg 已提交
2600 2601

	if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
2602 2603
	    elems.timeout_int &&
	    elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
J
Johannes Berg 已提交
2604
		u32 tu, ms;
2605
		tu = le32_to_cpu(elems.timeout_int->value);
J
Johannes Berg 已提交
2606
		ms = tu * 1024 / 1000;
J
Johannes Berg 已提交
2607 2608 2609
		sdata_info(sdata,
			   "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
			   mgmt->sa, tu, ms);
J
Johannes Berg 已提交
2610
		assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
2611
		assoc_data->timeout_started = true;
J
Johannes Berg 已提交
2612
		if (ms > IEEE80211_ASSOC_TIMEOUT)
2613 2614
			run_again(sdata, assoc_data->timeout);
		return;
J
Johannes Berg 已提交
2615 2616
	}

2617
	bss = assoc_data->bss;
J
Johannes Berg 已提交
2618 2619

	if (status_code != WLAN_STATUS_SUCCESS) {
J
Johannes Berg 已提交
2620 2621
		sdata_info(sdata, "%pM denied association (code=%d)\n",
			   mgmt->sa, status_code);
J
Johannes Berg 已提交
2622 2623
		ieee80211_destroy_assoc_data(sdata, false);
	} else {
2624
		if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
J
Johannes Berg 已提交
2625
			/* oops -- internal error -- send timeout for now */
2626
			ieee80211_destroy_assoc_data(sdata, false);
2627
			cfg80211_assoc_timeout(sdata->dev, bss);
2628
			return;
J
Johannes Berg 已提交
2629
		}
2630
		sdata_info(sdata, "associated\n");
2631 2632 2633 2634 2635 2636 2637

		/*
		 * 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
		 */
		ieee80211_destroy_assoc_data(sdata, true);
J
Johannes Berg 已提交
2638 2639
	}

2640
	cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len);
J
Johannes Berg 已提交
2641
}
J
Johannes Berg 已提交
2642

2643
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
2644
				  struct ieee80211_mgmt *mgmt, size_t len,
2645
				  struct ieee80211_rx_status *rx_status,
2646
				  struct ieee802_11_elems *elems)
2647 2648 2649
{
	struct ieee80211_local *local = sdata->local;
	int freq;
2650
	struct ieee80211_bss *bss;
2651
	struct ieee80211_channel *channel;
2652

2653
	sdata_assert_lock(sdata);
2654

2655
	if (elems->ds_params)
2656 2657
		freq = ieee80211_channel_to_frequency(elems->ds_params[0],
						      rx_status->band);
2658 2659 2660 2661 2662 2663 2664 2665 2666
	else
		freq = rx_status->freq;

	channel = ieee80211_get_channel(local->hw.wiphy, freq);

	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
		return;

	bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
2667
					channel);
2668
	if (bss) {
2669
		ieee80211_rx_bss_put(local, bss);
2670 2671
		sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
	}
2672 2673 2674
}


2675
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
2676
					 struct sk_buff *skb)
2677
{
J
Johannes Berg 已提交
2678
	struct ieee80211_mgmt *mgmt = (void *)skb->data;
2679
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
2680 2681
	struct ieee80211_rx_status *rx_status = (void *) skb->cb;
	size_t baselen, len = skb->len;
2682 2683
	struct ieee802_11_elems elems;

2684 2685
	ifmgd = &sdata->u.mgd;

2686
	sdata_assert_lock(sdata);
2687

2688
	if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
2689 2690
		return; /* ignore ProbeResp to foreign address */

2691 2692 2693 2694 2695
	baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
	if (baselen > len)
		return;

	ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
2696
			       false, &elems);
2697

2698
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
2699

2700
	if (ifmgd->associated &&
2701
	    ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
2702
		ieee80211_reset_ap_probe(sdata);
J
Johannes Berg 已提交
2703 2704

	if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies &&
2705
	    ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) {
J
Johannes Berg 已提交
2706
		/* got probe response, continue with auth */
J
Johannes Berg 已提交
2707
		sdata_info(sdata, "direct probe responded\n");
J
Johannes Berg 已提交
2708 2709
		ifmgd->auth_data->tries = 0;
		ifmgd->auth_data->timeout = jiffies;
2710
		ifmgd->auth_data->timeout_started = true;
2711
		run_again(sdata, ifmgd->auth_data->timeout);
J
Johannes Berg 已提交
2712
	}
2713 2714
}

2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728
/*
 * This is the canonical list of information elements we care about,
 * the filter code also gives us all changes to the Microsoft OUI
 * (00:50:F2) vendor IE which is used for WMM which we need to track.
 *
 * 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 =
2729 2730 2731 2732 2733
	(1ULL << WLAN_EID_COUNTRY) |
	(1ULL << WLAN_EID_ERP_INFO) |
	(1ULL << WLAN_EID_CHANNEL_SWITCH) |
	(1ULL << WLAN_EID_PWR_CONSTRAINT) |
	(1ULL << WLAN_EID_HT_CAPABILITY) |
2734
	(1ULL << WLAN_EID_HT_OPERATION);
2735

2736 2737 2738
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_mgmt *mgmt, size_t len,
				     struct ieee80211_rx_status *rx_status)
2739
{
2740
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2741
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
2742 2743
	size_t baselen;
	struct ieee802_11_elems elems;
2744
	struct ieee80211_local *local = sdata->local;
J
Johannes Berg 已提交
2745 2746
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_channel *chan;
2747
	struct sta_info *sta;
2748
	u32 changed = 0;
2749
	bool erp_valid;
J
Johannes Berg 已提交
2750
	u8 erp_value = 0;
2751
	u32 ncrc;
2752
	u8 *bssid;
2753
	u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
2754

2755
	sdata_assert_lock(sdata);
2756

2757 2758 2759
	/* Process beacon from the current BSS */
	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
	if (baselen > len)
2760
		return;
2761

J
Johannes Berg 已提交
2762 2763 2764 2765
	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
	if (!chanctx_conf) {
		rcu_read_unlock();
2766
		return;
J
Johannes Berg 已提交
2767 2768
	}

2769
	if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
J
Johannes Berg 已提交
2770
		rcu_read_unlock();
2771
		return;
J
Johannes Berg 已提交
2772
	}
2773
	chan = chanctx_conf->def.chan;
J
Johannes Berg 已提交
2774
	rcu_read_unlock();
2775

2776
	if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
2777
	    ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
J
Johannes Berg 已提交
2778
		ieee802_11_parse_elems(mgmt->u.beacon.variable,
2779
				       len - baselen, false, &elems);
2780

2781
		ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
2782 2783 2784 2785
		if (elems.tim && !elems.parse_error) {
			const struct ieee80211_tim_ie *tim_ie = elems.tim;
			ifmgd->dtim_period = tim_ie->dtim_period;
		}
2786
		ifmgd->have_beacon = true;
2787
		ifmgd->assoc_data->need_beacon = false;
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798
		if (local->hw.flags & IEEE80211_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;
			if (elems.tim)
				sdata->vif.bss_conf.sync_dtim_count =
					elems.tim->dtim_count;
			else
				sdata->vif.bss_conf.sync_dtim_count = 0;
		}
J
Johannes Berg 已提交
2799 2800
		/* continue assoc process */
		ifmgd->assoc_data->timeout = jiffies;
2801
		ifmgd->assoc_data->timeout_started = true;
2802 2803
		run_again(sdata, ifmgd->assoc_data->timeout);
		return;
J
Johannes Berg 已提交
2804
	}
2805

J
Johannes Berg 已提交
2806
	if (!ifmgd->associated ||
2807
	    !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
2808
		return;
J
Johannes Berg 已提交
2809
	bssid = ifmgd->associated->bssid;
2810

2811 2812 2813 2814
	/* Track average RSSI from the Beacon frames of the current AP */
	ifmgd->last_beacon_signal = rx_status->signal;
	if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
		ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
2815
		ifmgd->ave_beacon_signal = rx_status->signal * 16;
2816
		ifmgd->last_cqm_event_signal = 0;
2817
		ifmgd->count_beacon_signal = 1;
2818
		ifmgd->last_ave_beacon_signal = 0;
2819 2820 2821 2822 2823
	} else {
		ifmgd->ave_beacon_signal =
			(IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
			 (16 - IEEE80211_SIGNAL_AVE_WEIGHT) *
			 ifmgd->ave_beacon_signal) / 16;
2824
		ifmgd->count_beacon_signal++;
2825
	}
2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838

	if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
		int sig = ifmgd->ave_beacon_signal;
		int last_sig = ifmgd->last_ave_beacon_signal;

		/*
		 * 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;
2839
			drv_rssi_callback(local, sdata, RSSI_EVENT_HIGH);
2840 2841 2842 2843
		} else if (sig < ifmgd->rssi_min_thold &&
			   (last_sig >= ifmgd->rssi_max_thold ||
			   last_sig == 0)) {
			ifmgd->last_ave_beacon_signal = sig;
2844
			drv_rssi_callback(local, sdata, RSSI_EVENT_LOW);
2845 2846 2847
		}
	}

2848
	if (bss_conf->cqm_rssi_thold &&
2849
	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
2850
	    !(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) {
2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871
		int sig = ifmgd->ave_beacon_signal / 16;
		int last_event = ifmgd->last_cqm_event_signal;
		int thold = bss_conf->cqm_rssi_thold;
		int hyst = bss_conf->cqm_rssi_hyst;
		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,
				GFP_KERNEL);
		} 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,
				GFP_KERNEL);
		}
	}

2872
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
J
Johannes Berg 已提交
2873
		mlme_dbg_ratelimited(sdata,
2874
				     "cancelling AP probe due to a received beacon\n");
2875
		ieee80211_reset_ap_probe(sdata);
2876 2877
	}

J
Johannes Berg 已提交
2878 2879 2880 2881
	/*
	 * Push the beacon loss detection into the future since
	 * we are processing a beacon from the AP just now.
	 */
2882
	ieee80211_sta_reset_beacon_monitor(sdata);
J
Johannes Berg 已提交
2883

2884 2885
	ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
	ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
2886
					  len - baselen, false, &elems,
2887 2888
					  care_about_ies, ncrc);

2889
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
2890 2891 2892
		bool directed_tim = ieee80211_check_tim(elems.tim,
							elems.tim_len,
							ifmgd->aid);
2893
		if (directed_tim) {
2894
			if (local->hw.conf.dynamic_ps_timeout > 0) {
2895 2896 2897 2898 2899
				if (local->hw.conf.flags & IEEE80211_CONF_PS) {
					local->hw.conf.flags &= ~IEEE80211_CONF_PS;
					ieee80211_hw_config(local,
							    IEEE80211_CONF_CHANGE_PS);
				}
2900
				ieee80211_send_nullfunc(local, sdata, 0);
2901
			} else if (!local->pspolling && sdata->u.mgd.powersave) {
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913
				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);
			}
2914 2915
		}
	}
J
Johannes Berg 已提交
2916

2917
	if (sdata->vif.p2p) {
J
Janusz Dziedzic 已提交
2918
		struct ieee80211_p2p_noa_attr noa = {};
2919 2920 2921 2922 2923
		int ret;

		ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
					    len - baselen,
					    IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
2924
					    (u8 *) &noa, sizeof(noa));
J
Janusz Dziedzic 已提交
2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940
		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));
2941 2942 2943 2944 2945
			changed |= BSS_CHANGED_P2P_PS;
			ifmgd->beacon_crc_valid = false;
		}
	}

2946
	if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
2947
		return;
2948
	ifmgd->beacon_crc = ncrc;
2949
	ifmgd->beacon_crc_valid = true;
2950

2951
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
2952

2953 2954 2955
	ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
					 &elems, true);

2956 2957
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
	    ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
2958 2959 2960
				     elems.wmm_param_len))
		changed |= BSS_CHANGED_QOS;

2961 2962
	/*
	 * If we haven't had a beacon before, tell the driver about the
2963
	 * DTIM period (and beacon timing if desired) now.
2964
	 */
2965
	if (!ifmgd->have_beacon) {
2966 2967 2968 2969 2970
		/* a few bogus AP send dtim_period = 0 or no TIM IE */
		if (elems.tim)
			bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
		else
			bss_conf->dtim_period = 1;
2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983

		if (local->hw.flags & IEEE80211_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;
			if (elems.tim)
				sdata->vif.bss_conf.sync_dtim_count =
					elems.tim->dtim_count;
			else
				sdata->vif.bss_conf.sync_dtim_count = 0;
		}

2984 2985
		changed |= BSS_CHANGED_BEACON_INFO;
		ifmgd->have_beacon = true;
2986 2987 2988 2989 2990

		mutex_lock(&local->iflist_mtx);
		ieee80211_recalc_ps(local, -1);
		mutex_unlock(&local->iflist_mtx);

2991
		ieee80211_recalc_ps_vif(sdata);
2992 2993
	}

2994
	if (elems.erp_info) {
J
Johannes Berg 已提交
2995 2996 2997 2998
		erp_valid = true;
		erp_value = elems.erp_info[0];
	} else {
		erp_valid = false;
2999
	}
J
Johannes Berg 已提交
3000 3001 3002
	changed |= ieee80211_handle_bss_capability(sdata,
			le16_to_cpu(mgmt->u.beacon.capab_info),
			erp_valid, erp_value);
3003

3004
	mutex_lock(&local->sta_mtx);
3005 3006
	sta = sta_info_get(sdata, bssid);

3007 3008 3009 3010 3011 3012
	if (ieee80211_config_bw(sdata, sta, elems.ht_operation,
				elems.vht_operation, bssid, &changed)) {
		mutex_unlock(&local->sta_mtx);
		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       WLAN_REASON_DEAUTH_LEAVING,
				       true, deauth_buf);
3013 3014
		cfg80211_tx_mlme_mgmt(sdata->dev, deauth_buf,
				      sizeof(deauth_buf));
3015
		return;
3016
	}
3017 3018 3019 3020

	if (sta && elems.opmode_notif)
		ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
					    rx_status->band, true);
3021
	mutex_unlock(&local->sta_mtx);
3022

3023 3024 3025
	if (elems.country_elem && elems.pwr_constr_elem &&
	    mgmt->u.probe_resp.capab_info &
				cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
3026 3027 3028 3029
		changed |= ieee80211_handle_pwr_constr(sdata, chan,
						       elems.country_elem,
						       elems.country_elem_len,
						       elems.pwr_constr_elem);
3030

3031
	ieee80211_bss_info_change_notify(sdata, changed);
3032 3033
}

3034 3035
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
				  struct sk_buff *skb)
3036 3037 3038 3039
{
	struct ieee80211_rx_status *rx_status;
	struct ieee80211_mgmt *mgmt;
	u16 fc;
3040 3041
	struct ieee802_11_elems elems;
	int ies_len;
3042 3043 3044 3045 3046

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

3047
	sdata_lock(sdata);
3048

J
Johannes Berg 已提交
3049 3050
	switch (fc & IEEE80211_FCTL_STYPE) {
	case IEEE80211_STYPE_BEACON:
3051
		ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
J
Johannes Berg 已提交
3052 3053 3054 3055 3056
		break;
	case IEEE80211_STYPE_PROBE_RESP:
		ieee80211_rx_mgmt_probe_resp(sdata, skb);
		break;
	case IEEE80211_STYPE_AUTH:
3057
		ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
3058 3059
		break;
	case IEEE80211_STYPE_DEAUTH:
3060
		ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
3061 3062
		break;
	case IEEE80211_STYPE_DISASSOC:
3063
		ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
3064 3065 3066
		break;
	case IEEE80211_STYPE_ASSOC_RESP:
	case IEEE80211_STYPE_REASSOC_RESP:
3067
		ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);
J
Johannes Berg 已提交
3068 3069
		break;
	case IEEE80211_STYPE_ACTION:
3070
		if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
3071 3072 3073
			ies_len = skb->len -
				  offsetof(struct ieee80211_mgmt,
					   u.action.u.chan_switch.variable);
3074 3075 3076 3077 3078 3079

			if (ies_len < 0)
				break;

			ieee802_11_parse_elems(
				mgmt->u.action.u.chan_switch.variable,
3080
				ies_len, true, &elems);
3081 3082 3083 3084

			if (elems.parse_error)
				break;

3085 3086
			ieee80211_sta_process_chanswitch(sdata,
							 rx_status->mactime,
3087
							 &elems, false);
3088 3089 3090 3091 3092 3093 3094 3095 3096 3097
		} 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;

			ieee802_11_parse_elems(
				mgmt->u.action.u.ext_chan_switch.variable,
3098
				ies_len, true, &elems);
3099 3100 3101 3102 3103 3104 3105 3106

			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 已提交
3107
			ieee80211_sta_process_chanswitch(sdata,
3108
							 rx_status->mactime,
3109
							 &elems, false);
3110
		}
3111
		break;
3112
	}
3113
	sdata_unlock(sdata);
3114 3115
}

J
Johannes Berg 已提交
3116
static void ieee80211_sta_timer(unsigned long data)
3117
{
J
Johannes Berg 已提交
3118 3119
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
3120

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

3124
static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
3125
					  u8 *bssid, u8 reason, bool tx)
3126
{
3127
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3128

3129
	ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
3130
			       tx, frame_buf);
3131

3132 3133
	cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
			      IEEE80211_DEAUTH_FRAME_LEN);
3134 3135
}

J
Johannes Berg 已提交
3136 3137 3138 3139 3140
static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
3141
	u32 tx_flags = 0;
J
Johannes Berg 已提交
3142

3143
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
3144 3145 3146 3147 3148 3149 3150

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

	auth_data->tries++;

	if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
J
Johannes Berg 已提交
3151 3152
		sdata_info(sdata, "authentication with %pM timed out\n",
			   auth_data->bss->bssid);
J
Johannes Berg 已提交
3153 3154 3155 3156 3157 3158 3159 3160 3161 3162

		/*
		 * 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;
	}

J
Johannes Berg 已提交
3163 3164
	drv_mgd_prepare_tx(local, sdata);

J
Johannes Berg 已提交
3165
	if (auth_data->bss->proberesp_ies) {
3166 3167 3168
		u16 trans = 1;
		u16 status = 0;

J
Johannes Berg 已提交
3169 3170 3171
		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 已提交
3172 3173

		auth_data->expected_transaction = 2;
3174 3175 3176 3177 3178 3179 3180

		if (auth_data->algorithm == WLAN_AUTH_SAE) {
			trans = auth_data->sae_trans;
			status = auth_data->sae_status;
			auth_data->expected_transaction = trans;
		}

3181 3182 3183 3184
		if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
			tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
				   IEEE80211_TX_INTFL_MLME_CONN_TX;

3185 3186
		ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
				    auth_data->data, auth_data->data_len,
J
Johannes Berg 已提交
3187
				    auth_data->bss->bssid,
3188 3189
				    auth_data->bss->bssid, NULL, 0, 0,
				    tx_flags);
J
Johannes Berg 已提交
3190 3191 3192
	} else {
		const u8 *ssidie;

J
Johannes Berg 已提交
3193 3194 3195
		sdata_info(sdata, "direct probe to %pM (try %d/%i)\n",
			   auth_data->bss->bssid, auth_data->tries,
			   IEEE80211_AUTH_MAX_TRIES);
J
Johannes Berg 已提交
3196

3197
		rcu_read_lock();
J
Johannes Berg 已提交
3198
		ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
3199 3200
		if (!ssidie) {
			rcu_read_unlock();
J
Johannes Berg 已提交
3201
			return -EINVAL;
3202
		}
J
Johannes Berg 已提交
3203 3204 3205 3206 3207
		/*
		 * Direct probe is sent to broadcast address as some APs
		 * will not answer to direct packet in unassociated state.
		 */
		ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
3208
					 NULL, 0, (u32) -1, true, 0,
J
Johannes Berg 已提交
3209
					 auth_data->bss->channel, false);
3210
		rcu_read_unlock();
J
Johannes Berg 已提交
3211 3212
	}

3213
	if (tx_flags == 0) {
3214
		auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
3215
		auth_data->timeout_started = true;
3216
		run_again(sdata, auth_data->timeout);
3217
	} else {
3218 3219 3220 3221
		auth_data->timeout =
			round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
		auth_data->timeout_started = true;
		run_again(sdata, auth_data->timeout);
3222
	}
J
Johannes Berg 已提交
3223 3224 3225 3226 3227 3228 3229 3230 3231

	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;

3232
	sdata_assert_lock(sdata);
J
Johannes Berg 已提交
3233 3234 3235

	assoc_data->tries++;
	if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
J
Johannes Berg 已提交
3236 3237
		sdata_info(sdata, "association with %pM timed out\n",
			   assoc_data->bss->bssid);
J
Johannes Berg 已提交
3238 3239 3240 3241 3242 3243 3244 3245 3246 3247

		/*
		 * 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 已提交
3248 3249 3250
	sdata_info(sdata, "associate with %pM (try %d/%d)\n",
		   assoc_data->bss->bssid, assoc_data->tries,
		   IEEE80211_ASSOC_MAX_TRIES);
J
Johannes Berg 已提交
3251 3252
	ieee80211_send_assoc(sdata);

3253 3254
	if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
		assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
3255
		assoc_data->timeout_started = true;
3256
		run_again(sdata, assoc_data->timeout);
3257
	} else {
3258 3259 3260 3261 3262
		assoc_data->timeout =
			round_jiffies_up(jiffies +
					 IEEE80211_ASSOC_TIMEOUT_LONG);
		assoc_data->timeout_started = true;
		run_again(sdata, assoc_data->timeout);
3263
	}
J
Johannes Berg 已提交
3264 3265 3266 3267

	return 0;
}

3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279
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);
}

3280
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
3281 3282
{
	struct ieee80211_local *local = sdata->local;
3283
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
3284

3285
	sdata_lock(sdata);
3286

3287 3288 3289 3290 3291 3292 3293 3294 3295 3296
	if (ifmgd->status_received) {
		__le16 fc = ifmgd->status_fc;
		bool status_acked = ifmgd->status_acked;

		ifmgd->status_received = false;
		if (ifmgd->auth_data &&
		    (ieee80211_is_probe_req(fc) || ieee80211_is_auth(fc))) {
			if (status_acked) {
				ifmgd->auth_data->timeout =
					jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;
3297
				run_again(sdata, ifmgd->auth_data->timeout);
3298 3299 3300
			} else {
				ifmgd->auth_data->timeout = jiffies - 1;
			}
3301
			ifmgd->auth_data->timeout_started = true;
3302 3303 3304 3305 3306 3307
		} 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;
3308
				run_again(sdata, ifmgd->assoc_data->timeout);
3309 3310 3311
			} else {
				ifmgd->assoc_data->timeout = jiffies - 1;
			}
3312
			ifmgd->assoc_data->timeout_started = true;
3313 3314 3315
		}
	}

3316
	if (ifmgd->auth_data && ifmgd->auth_data->timeout_started &&
J
Johannes Berg 已提交
3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330
	    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);
		} else if (ieee80211_probe_auth(sdata)) {
			u8 bssid[ETH_ALEN];

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

			ieee80211_destroy_auth_data(sdata, false);

3331
			cfg80211_auth_timeout(sdata->dev, bssid);
J
Johannes Berg 已提交
3332
		}
3333
	} else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
3334
		run_again(sdata, ifmgd->auth_data->timeout);
J
Johannes Berg 已提交
3335

3336
	if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
J
Johannes Berg 已提交
3337
	    time_after(jiffies, ifmgd->assoc_data->timeout)) {
3338
		if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) ||
J
Johannes Berg 已提交
3339
		    ieee80211_do_assoc(sdata)) {
3340
			struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
J
Johannes Berg 已提交
3341 3342

			ieee80211_destroy_assoc_data(sdata, false);
3343
			cfg80211_assoc_timeout(sdata->dev, bss);
J
Johannes Berg 已提交
3344
		}
3345
	} else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
3346
		run_again(sdata, ifmgd->assoc_data->timeout);
J
Johannes Berg 已提交
3347

3348
	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL &&
J
Johannes Berg 已提交
3349
	    ifmgd->associated) {
3350
		u8 bssid[ETH_ALEN];
3351
		int max_tries;
3352

3353
		memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
3354

3355
		if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
3356
			max_tries = max_nullfunc_tries;
3357
		else
3358
			max_tries = max_probe_tries;
3359

3360 3361 3362
		/* ACK received for nullfunc probing frame */
		if (!ifmgd->probe_send_count)
			ieee80211_reset_ap_probe(sdata);
3363 3364
		else if (ifmgd->nullfunc_failed) {
			if (ifmgd->probe_send_count < max_tries) {
J
Johannes Berg 已提交
3365 3366 3367 3368
				mlme_dbg(sdata,
					 "No ack for nullfunc frame to AP %pM, try %d/%i\n",
					 bssid, ifmgd->probe_send_count,
					 max_tries);
3369 3370
				ieee80211_mgd_probe_ap_send(sdata);
			} else {
J
Johannes Berg 已提交
3371 3372 3373
				mlme_dbg(sdata,
					 "No ack for nullfunc frame to AP %pM, disconnecting.\n",
					 bssid);
3374
				ieee80211_sta_connection_lost(sdata, bssid,
3375 3376
					WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
					false);
3377 3378
			}
		} else if (time_is_after_jiffies(ifmgd->probe_timeout))
3379
			run_again(sdata, ifmgd->probe_timeout);
3380
		else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
J
Johannes Berg 已提交
3381 3382 3383
			mlme_dbg(sdata,
				 "Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
				 bssid, probe_wait_ms);
3384
			ieee80211_sta_connection_lost(sdata, bssid,
3385
				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false);
3386
		} else if (ifmgd->probe_send_count < max_tries) {
J
Johannes Berg 已提交
3387 3388 3389 3390
			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);
3391 3392
			ieee80211_mgd_probe_ap_send(sdata);
		} else {
J
Johannes Berg 已提交
3393 3394 3395 3396
			/*
			 * We actually lost the connection ... or did we?
			 * Let's make sure!
			 */
3397 3398 3399 3400
			wiphy_debug(local->hw.wiphy,
				    "%s: No probe response from AP %pM"
				    " after %dms, disconnecting.\n",
				    sdata->name,
3401
				    bssid, probe_wait_ms);
3402

3403
			ieee80211_sta_connection_lost(sdata, bssid,
3404
				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false);
J
Johannes Berg 已提交
3405 3406 3407
		}
	}

3408
	sdata_unlock(sdata);
3409 3410
}

J
Johannes Berg 已提交
3411 3412 3413 3414 3415 3416 3417 3418 3419
static void ieee80211_sta_bcn_mon_timer(unsigned long data)
{
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
	struct ieee80211_local *local = sdata->local;

	if (local->quiescing)
		return;

3420
	sdata->u.mgd.connection_loss = false;
3421 3422
	ieee80211_queue_work(&sdata->local->hw,
			     &sdata->u.mgd.beacon_connection_loss_work);
J
Johannes Berg 已提交
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434
}

static void ieee80211_sta_conn_mon_timer(unsigned long data)
{
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_local *local = sdata->local;

	if (local->quiescing)
		return;

3435
	ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
J
Johannes Berg 已提交
3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446
}

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 已提交
3447 3448
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
3449 3450
	u32 flags;

3451
	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
3452
		__ieee80211_stop_poll(sdata);
3453

J
Johannes Berg 已提交
3454
		/* let's probe the connection once */
3455 3456 3457 3458
		flags = sdata->local->hw.flags;
		if (!(flags & IEEE80211_HW_CONNECTION_MONITOR))
			ieee80211_queue_work(&sdata->local->hw,
					     &sdata->u.mgd.monitor_work);
J
Johannes Berg 已提交
3459
		/* and do all the other regular work too */
J
Johannes Berg 已提交
3460
		ieee80211_queue_work(&sdata->local->hw, &sdata->work);
3461
	}
J
Johannes Berg 已提交
3462
}
3463

3464 3465 3466 3467 3468
#ifdef CONFIG_PM
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

3469
	sdata_lock(sdata);
3470
	if (!ifmgd->associated) {
3471
		sdata_unlock(sdata);
3472 3473 3474 3475 3476 3477 3478 3479 3480 3481
		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);
3482
		sdata_unlock(sdata);
3483 3484
		return;
	}
3485
	sdata_unlock(sdata);
3486 3487 3488
}
#endif

J
Johannes Berg 已提交
3489 3490
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
3491
{
3492
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
3493

3494
	ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
3495
	INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
3496
	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
3497 3498
	INIT_WORK(&ifmgd->beacon_connection_loss_work,
		  ieee80211_beacon_connection_loss_work);
3499 3500
	INIT_WORK(&ifmgd->csa_connection_drop_work,
		  ieee80211_csa_connection_drop_work);
3501
	INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
3502
	setup_timer(&ifmgd->timer, ieee80211_sta_timer,
S
Sujith 已提交
3503
		    (unsigned long) sdata);
J
Johannes Berg 已提交
3504 3505 3506 3507
	setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
		    (unsigned long) sdata);
	setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer,
		    (unsigned long) sdata);
3508
	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
J
Johannes Berg 已提交
3509 3510
		    (unsigned long) sdata);

3511
	ifmgd->flags = 0;
3512
	ifmgd->powersave = sdata->wdev.ps;
3513 3514
	ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues;
	ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
J
Janusz Dziedzic 已提交
3515
	ifmgd->p2p_noa_index = -1;
J
Johannes Berg 已提交
3516

3517 3518 3519 3520
	if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
		ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
	else
		ifmgd->req_smps = IEEE80211_SMPS_OFF;
3521 3522
}

3523 3524
/* scan finished notification */
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
J
Johannes Berg 已提交
3525
{
3526
	struct ieee80211_sub_if_data *sdata;
J
Johannes Berg 已提交
3527

3528 3529
	/* Restart STA timers */
	rcu_read_lock();
3530 3531 3532 3533
	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
		if (ieee80211_sdata_running(sdata))
			ieee80211_restart_sta_timer(sdata);
	}
3534 3535
	rcu_read_unlock();
}
J
Johannes Berg 已提交
3536

3537 3538 3539 3540 3541 3542 3543
int ieee80211_max_network_latency(struct notifier_block *nb,
				  unsigned long data, void *dummy)
{
	s32 latency_usec = (s32) data;
	struct ieee80211_local *local =
		container_of(nb, struct ieee80211_local,
			     network_latency_notifier);
3544

3545 3546 3547
	mutex_lock(&local->iflist_mtx);
	ieee80211_recalc_ps(local, latency_usec);
	mutex_unlock(&local->iflist_mtx);
3548

3549
	return 0;
J
Johannes Berg 已提交
3550 3551
}

J
Johannes Berg 已提交
3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563
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;

3564
	ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
J
Johannes Berg 已提交
3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576
	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;

3577
	vht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
J
Johannes Berg 已提交
3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595
	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;
}

3596 3597
static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
				  struct cfg80211_bss *cbss)
3598 3599 3600
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3601
	const struct ieee80211_ht_operation *ht_oper = NULL;
J
Johannes Berg 已提交
3602
	const struct ieee80211_vht_operation *vht_oper = NULL;
3603
	struct ieee80211_supported_band *sband;
3604
	struct cfg80211_chan_def chandef;
J
Johannes Berg 已提交
3605
	int ret;
3606

3607 3608
	sband = local->hw.wiphy->bands[cbss->channel->band];

J
Johannes Berg 已提交
3609 3610 3611 3612
	ifmgd->flags &= ~(IEEE80211_STA_DISABLE_40MHZ |
			  IEEE80211_STA_DISABLE_80P80MHZ |
			  IEEE80211_STA_DISABLE_160MHZ);

3613 3614
	rcu_read_lock();

J
Johannes Berg 已提交
3615 3616
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
	    sband->ht_cap.ht_supported) {
3617
		const u8 *ht_oper_ie, *ht_cap;
3618

3619
		ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
3620 3621
		if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
			ht_oper = (void *)(ht_oper_ie + 2);
3622 3623 3624 3625 3626 3627

		ht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
		if (!ht_cap || ht_cap[1] < sizeof(struct ieee80211_ht_cap)) {
			ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
			ht_oper = NULL;
		}
3628 3629
	}

J
Johannes Berg 已提交
3630 3631
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
	    sband->vht_cap.vht_supported) {
3632
		const u8 *vht_oper_ie, *vht_cap;
J
Johannes Berg 已提交
3633

3634 3635
		vht_oper_ie = ieee80211_bss_get_ie(cbss,
						   WLAN_EID_VHT_OPERATION);
J
Johannes Berg 已提交
3636 3637 3638 3639
		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 已提交
3640
			sdata_info(sdata,
J
Johannes Berg 已提交
3641
				   "AP advertised VHT without HT, disabling both\n");
3642 3643
			ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
			ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
3644
		}
3645 3646 3647 3648 3649 3650

		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;
		}
3651 3652
	}

J
Johannes Berg 已提交
3653 3654 3655
	ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
						     cbss->channel,
						     ht_oper, vht_oper,
3656
						     &chandef, false);
3657

J
Johannes Berg 已提交
3658 3659
	sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
				      local->rx_chains);
3660

3661 3662
	rcu_read_unlock();

3663 3664 3665
	/* will change later if needed */
	sdata->smps_mode = IEEE80211_SMPS_OFF;

J
Johannes Berg 已提交
3666 3667 3668 3669 3670 3671 3672
	/*
	 * 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);
3673 3674 3675 3676 3677 3678

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

3679
	while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
3680
		ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
3681 3682 3683
		ret = ieee80211_vif_use_channel(sdata, &chandef,
						IEEE80211_CHANCTX_SHARED);
	}
J
Johannes Berg 已提交
3684
	return ret;
3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710
}

static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
				     struct cfg80211_bss *cbss, bool assoc)
{
	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;
	bool have_sta = false;
	int err;

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

	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;
	}
J
Johannes Berg 已提交
3711
	if (new_sta) {
3712 3713 3714
		u32 rates = 0, basic_rates = 0;
		bool have_higher_than_11mbit;
		int min_rate = INT_MAX, min_rate_index = -1;
3715
		struct ieee80211_chanctx_conf *chanctx_conf;
3716
		struct ieee80211_supported_band *sband;
J
Johannes Berg 已提交
3717
		const struct cfg80211_bss_ies *ies;
3718 3719
		int shift;
		u32 rate_flags;
3720 3721 3722 3723 3724 3725

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

		err = ieee80211_prep_channel(sdata, cbss);
		if (err) {
			sta_info_free(local, new_sta);
3726
			return -EINVAL;
3727
		}
3728 3729 3730 3731 3732 3733 3734 3735 3736 3737
		shift = ieee80211_vif_get_shift(&sdata->vif);

		rcu_read_lock();
		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
		if (WARN_ON(!chanctx_conf)) {
			rcu_read_unlock();
			return -EINVAL;
		}
		rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
		rcu_read_unlock();
3738 3739 3740 3741 3742

		ieee80211_get_rates(sband, bss->supp_rates,
				    bss->supp_rates_len,
				    &rates, &basic_rates,
				    &have_higher_than_11mbit,
3743 3744
				    &min_rate, &min_rate_index,
				    shift, rate_flags);
3745 3746 3747 3748 3749 3750 3751 3752 3753 3754

		/*
		 * 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.
		 */
		if (!basic_rates && min_rate_index >= 0) {
J
Johannes Berg 已提交
3755 3756
			sdata_info(sdata,
				   "No basic rates, using min rate instead\n");
3757 3758 3759
			basic_rates = BIT(min_rate_index);
		}

J
Johannes Berg 已提交
3760
		new_sta->sta.supp_rates[cbss->channel->band] = rates;
3761 3762 3763
		sdata->vif.bss_conf.basic_rates = basic_rates;

		/* cf. IEEE 802.11 9.2.12 */
J
Johannes Berg 已提交
3764
		if (cbss->channel->band == IEEE80211_BAND_2GHZ &&
3765 3766 3767 3768 3769 3770 3771
		    have_higher_than_11mbit)
			sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
		else
			sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;

		memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN);

3772 3773
		/* set timing information */
		sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
J
Johannes Berg 已提交
3774
		rcu_read_lock();
3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800
		ies = rcu_dereference(cbss->beacon_ies);
		if (ies) {
			const u8 *tim_ie;

			sdata->vif.bss_conf.sync_tsf = ies->tsf;
			sdata->vif.bss_conf.sync_device_ts =
				bss->device_ts_beacon;
			tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
						  ies->data, ies->len);
			if (tim_ie && tim_ie[1] >= 2)
				sdata->vif.bss_conf.sync_dtim_count = tim_ie[2];
			else
				sdata->vif.bss_conf.sync_dtim_count = 0;
		} else if (!(local->hw.flags &
					IEEE80211_HW_TIMING_BEACON_ONLY)) {
			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 已提交
3801
		rcu_read_unlock();
3802 3803

		/* tell driver about BSSID, basic rates and timing */
3804
		ieee80211_bss_info_change_notify(sdata,
3805 3806
			BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |
			BSS_CHANGED_BEACON_INT);
3807 3808

		if (assoc)
J
Johannes Berg 已提交
3809
			sta_info_pre_move_state(new_sta, IEEE80211_STA_AUTH);
3810

J
Johannes Berg 已提交
3811 3812
		err = sta_info_insert(new_sta);
		new_sta = NULL;
3813
		if (err) {
J
Johannes Berg 已提交
3814 3815 3816
			sdata_info(sdata,
				   "failed to insert STA entry for the AP (error %d)\n",
				   err);
3817 3818 3819
			return err;
		}
	} else
3820
		WARN_ON_ONCE(!ether_addr_equal(ifmgd->bssid, cbss->bssid));
3821 3822 3823 3824

	return 0;
}

3825 3826 3827
/* config hooks */
int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
		       struct cfg80211_auth_request *req)
J
Johannes Berg 已提交
3828
{
J
Johannes Berg 已提交
3829 3830 3831
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_mgd_auth_data *auth_data;
3832
	u16 auth_alg;
J
Johannes Berg 已提交
3833 3834 3835
	int err;

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

3837 3838 3839 3840 3841
	switch (req->auth_type) {
	case NL80211_AUTHTYPE_OPEN_SYSTEM:
		auth_alg = WLAN_AUTH_OPEN;
		break;
	case NL80211_AUTHTYPE_SHARED_KEY:
J
Johannes Berg 已提交
3842
		if (IS_ERR(local->wep_tx_tfm))
3843
			return -EOPNOTSUPP;
3844 3845 3846 3847 3848 3849 3850 3851
		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;
3852 3853 3854
	case NL80211_AUTHTYPE_SAE:
		auth_alg = WLAN_AUTH_SAE;
		break;
3855 3856
	default:
		return -EOPNOTSUPP;
J
Johannes Berg 已提交
3857
	}
3858

3859 3860
	auth_data = kzalloc(sizeof(*auth_data) + req->sae_data_len +
			    req->ie_len, GFP_KERNEL);
J
Johannes Berg 已提交
3861
	if (!auth_data)
J
Johannes Berg 已提交
3862
		return -ENOMEM;
3863

J
Johannes Berg 已提交
3864
	auth_data->bss = req->bss;
3865

3866 3867 3868 3869 3870 3871 3872 3873 3874
	if (req->sae_data_len >= 4) {
		__le16 *pos = (__le16 *) req->sae_data;
		auth_data->sae_trans = le16_to_cpu(pos[0]);
		auth_data->sae_status = le16_to_cpu(pos[1]);
		memcpy(auth_data->data, req->sae_data + 4,
		       req->sae_data_len - 4);
		auth_data->data_len += req->sae_data_len - 4;
	}

3875
	if (req->ie && req->ie_len) {
3876 3877 3878
		memcpy(&auth_data->data[auth_data->data_len],
		       req->ie, req->ie_len);
		auth_data->data_len += req->ie_len;
J
Johannes Berg 已提交
3879
	}
3880

J
Johannes Berg 已提交
3881
	if (req->key && req->key_len) {
J
Johannes Berg 已提交
3882 3883 3884
		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 已提交
3885 3886
	}

J
Johannes Berg 已提交
3887
	auth_data->algorithm = auth_alg;
J
Johannes Berg 已提交
3888

J
Johannes Berg 已提交
3889
	/* try to authenticate/probe */
3890

J
Johannes Berg 已提交
3891 3892 3893 3894
	if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||
	    ifmgd->assoc_data) {
		err = -EBUSY;
		goto err_free;
3895 3896
	}

J
Johannes Berg 已提交
3897 3898
	if (ifmgd->auth_data)
		ieee80211_destroy_auth_data(sdata, false);
3899

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

3903 3904 3905 3906 3907 3908 3909
	if (ifmgd->associated) {
		u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];

		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       WLAN_REASON_UNSPECIFIED,
				       false, frame_buf);

3910 3911
		cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
				      sizeof(frame_buf));
3912
	}
J
Johannes Berg 已提交
3913

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

3916 3917
	err = ieee80211_prep_connection(sdata, req->bss, false);
	if (err)
J
Johannes Berg 已提交
3918
		goto err_clear;
J
Johannes Berg 已提交
3919

J
Johannes Berg 已提交
3920 3921 3922 3923 3924 3925 3926
	err = ieee80211_probe_auth(sdata);
	if (err) {
		sta_info_destroy_addr(sdata, req->bss->bssid);
		goto err_clear;
	}

	/* hold our own reference */
3927
	cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
3928
	return 0;
J
Johannes Berg 已提交
3929 3930

 err_clear:
3931 3932
	memset(ifmgd->bssid, 0, ETH_ALEN);
	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
J
Johannes Berg 已提交
3933 3934 3935 3936
	ifmgd->auth_data = NULL;
 err_free:
	kfree(auth_data);
	return err;
J
Johannes Berg 已提交
3937 3938
}

3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976
static bool ieee80211_usable_wmm_params(struct ieee80211_sub_if_data *sdata,
					const u8 *wmm_param, int len)
{
	const u8 *pos;
	size_t left;

	if (len < 8)
		return false;

	if (wmm_param[5] != 1 /* version */)
		return false;

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

	for (; left >= 4; left -= 4, pos += 4) {
		u8 aifsn = pos[0] & 0x0f;
		u8 ecwmin = pos[1] & 0x0f;
		u8 ecwmax = (pos[1] & 0xf0) >> 4;
		int aci = (pos[0] >> 5) & 0x03;

		if (aifsn < 2) {
			sdata_info(sdata,
				   "AP has invalid WMM params (AIFSN=%d for ACI %d), disabling WMM\n",
				   aifsn, aci);
			return false;
		}
		if (ecwmin > ecwmax) {
			sdata_info(sdata,
				   "AP has invalid WMM params (ECWmin/max=%d/%d for ACI %d), disabling WMM\n",
				   ecwmin, ecwmax, aci);
			return false;
		}
	}

	return true;
}

3977 3978
int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
			struct cfg80211_assoc_request *req)
3979
{
J
Johannes Berg 已提交
3980
	struct ieee80211_local *local = sdata->local;
3981
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3982
	struct ieee80211_bss *bss = (void *)req->bss->priv;
J
Johannes Berg 已提交
3983
	struct ieee80211_mgd_assoc_data *assoc_data;
3984
	const struct cfg80211_bss_ies *beacon_ies;
J
Johannes Berg 已提交
3985
	struct ieee80211_supported_band *sband;
3986
	const u8 *ssidie, *ht_ie, *vht_ie;
3987
	int i, err;
3988

J
Johannes Berg 已提交
3989 3990 3991 3992
	assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL);
	if (!assoc_data)
		return -ENOMEM;

3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003
	rcu_read_lock();
	ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
	if (!ssidie) {
		rcu_read_unlock();
		kfree(assoc_data);
		return -EINVAL;
	}
	memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
	assoc_data->ssid_len = ssidie[1];
	rcu_read_unlock();

4004 4005 4006 4007 4008 4009 4010
	if (ifmgd->associated) {
		u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];

		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       WLAN_REASON_UNSPECIFIED,
				       false, frame_buf);

4011 4012
		cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
				      sizeof(frame_buf));
4013
	}
J
Johannes Berg 已提交
4014 4015 4016 4017

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

J
Johannes Berg 已提交
4020 4021 4022 4023
	if (ifmgd->assoc_data) {
		err = -EBUSY;
		goto err_free;
	}
4024

J
Johannes Berg 已提交
4025 4026 4027 4028
	if (ifmgd->auth_data) {
		bool match;

		/* keep sta info, bssid if matching */
4029
		match = ether_addr_equal(ifmgd->bssid, req->bss->bssid);
J
Johannes Berg 已提交
4030
		ieee80211_destroy_auth_data(sdata, match);
4031 4032
	}

J
Johannes Berg 已提交
4033
	/* prepare assoc data */
4034

4035 4036
	ifmgd->beacon_crc_valid = false;

4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072
	assoc_data->wmm = bss->wmm_used &&
			  (local->hw.queues >= IEEE80211_NUM_ACS);
	if (assoc_data->wmm) {
		/* try to check validity of WMM params IE */
		const struct cfg80211_bss_ies *ies;
		const u8 *wp, *start, *end;

		rcu_read_lock();
		ies = rcu_dereference(req->bss->ies);
		start = ies->data;
		end = start + ies->len;

		while (true) {
			wp = cfg80211_find_vendor_ie(
				WLAN_OUI_MICROSOFT,
				WLAN_OUI_TYPE_MICROSOFT_WMM,
				start, end - start);
			if (!wp)
				break;
			start = wp + wp[1] + 2;
			/* if this IE is too short, try the next */
			if (wp[1] <= 4)
				continue;
			/* if this IE is WMM params, we found what we wanted */
			if (wp[6] == 1)
				break;
		}

		if (!wp || !ieee80211_usable_wmm_params(sdata, wp + 2,
							wp[1] - 2)) {
			assoc_data->wmm = false;
			ifmgd->flags |= IEEE80211_STA_DISABLE_WMM;
		}
		rcu_read_unlock();
	}

J
Johannes Berg 已提交
4073 4074 4075 4076 4077 4078 4079
	/*
	 * 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.
	 */
4080
	for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) {
4081 4082
		if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
		    req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
4083
		    req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
4084
			ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
4085
			ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
4086
			netdev_info(sdata->dev,
4087
				    "disabling HT/VHT due to WEP/TKIP use\n");
4088 4089
		}
	}
4090

4091
	if (req->flags & ASSOC_REQ_DISABLE_HT) {
4092
		ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
4093 4094
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
	}
B
Ben Greear 已提交
4095

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

J
Johannes Berg 已提交
4099 4100 4101
	/* Also disable HT if we don't support it or the AP doesn't use WMM */
	sband = local->hw.wiphy->bands[req->bss->channel->band];
	if (!sband->ht_cap.ht_supported ||
4102 4103
	    local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
	    ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
4104
		ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
4105 4106
		if (!bss->wmm_used &&
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
4107 4108
			netdev_info(sdata->dev,
				    "disabling HT as WMM/QoS is not supported by the AP\n");
4109
	}
J
Johannes Berg 已提交
4110

4111 4112
	/* disable VHT if we don't support it or the AP doesn't use WMM */
	if (!sband->vht_cap.vht_supported ||
4113 4114
	    local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used ||
	    ifmgd->flags & IEEE80211_STA_DISABLE_WMM) {
4115
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
4116 4117
		if (!bss->wmm_used &&
		    !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM))
4118 4119
			netdev_info(sdata->dev,
				    "disabling VHT as WMM/QoS is not supported by the AP\n");
4120 4121
	}

B
Ben Greear 已提交
4122 4123 4124 4125
	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));

4126 4127 4128 4129
	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));

4130
	if (req->ie && req->ie_len) {
J
Johannes Berg 已提交
4131 4132 4133
		memcpy(assoc_data->ie, req->ie, req->ie_len);
		assoc_data->ie_len = req->ie_len;
	}
4134

J
Johannes Berg 已提交
4135
	assoc_data->bss = req->bss;
4136

J
Johannes Berg 已提交
4137 4138
	if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
		if (ifmgd->powersave)
4139
			sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
J
Johannes Berg 已提交
4140
		else
4141
			sdata->smps_mode = IEEE80211_SMPS_OFF;
J
Johannes Berg 已提交
4142
	} else
4143
		sdata->smps_mode = ifmgd->req_smps;
J
Johannes Berg 已提交
4144

J
Johannes Berg 已提交
4145 4146 4147
	assoc_data->capability = req->bss->capability;
	assoc_data->supp_rates = bss->supp_rates;
	assoc_data->supp_rates_len = bss->supp_rates_len;
4148

4149
	rcu_read_lock();
4150 4151 4152 4153 4154
	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;
	else
4155
		ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
4156 4157 4158 4159 4160 4161
	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));
	else
		ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
4162
	rcu_read_unlock();
4163

K
Kalle Valo 已提交
4164
	if (bss->wmm_used && bss->uapsd_supported &&
4165 4166
	    (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) &&
	    sdata->wmm_acm != 0xff) {
4167
		assoc_data->uapsd = true;
K
Kalle Valo 已提交
4168 4169
		ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
	} else {
4170
		assoc_data->uapsd = false;
K
Kalle Valo 已提交
4171 4172 4173
		ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
	}

4174
	if (req->prev_bssid)
J
Johannes Berg 已提交
4175
		memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN);
4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189

	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;
	}

	if (req->crypto.control_port)
		ifmgd->flags |= IEEE80211_STA_CONTROL_PORT;
	else
		ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;

4190 4191 4192
	sdata->control_port_protocol = req->crypto.control_port_ethertype;
	sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;

J
Johannes Berg 已提交
4193 4194 4195
	/* kick off associate process */

	ifmgd->assoc_data = assoc_data;
4196
	ifmgd->dtim_period = 0;
4197
	ifmgd->have_beacon = false;
J
Johannes Berg 已提交
4198

4199 4200 4201
	err = ieee80211_prep_connection(sdata, req->bss, true);
	if (err)
		goto err_clear;
J
Johannes Berg 已提交
4202

4203 4204
	rcu_read_lock();
	beacon_ies = rcu_dereference(req->bss->beacon_ies);
4205

4206 4207 4208 4209 4210 4211 4212 4213 4214
	if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC &&
	    !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);
4215
		assoc_data->timeout_started = true;
4216 4217 4218 4219 4220
		assoc_data->need_beacon = true;
	} else if (beacon_ies) {
		const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
						    beacon_ies->data,
						    beacon_ies->len);
4221 4222
		u8 dtim_count = 0;

4223 4224 4225 4226
		if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
			const struct ieee80211_tim_ie *tim;
			tim = (void *)(tim_ie + 2);
			ifmgd->dtim_period = tim->dtim_period;
4227
			dtim_count = tim->dtim_count;
4228
		}
4229
		ifmgd->have_beacon = true;
J
Johannes Berg 已提交
4230
		assoc_data->timeout = jiffies;
4231
		assoc_data->timeout_started = true;
4232 4233 4234 4235 4236 4237 4238

		if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
			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;
		}
4239 4240
	} else {
		assoc_data->timeout = jiffies;
4241
		assoc_data->timeout_started = true;
J
Johannes Berg 已提交
4242
	}
4243 4244
	rcu_read_unlock();

4245
	run_again(sdata, assoc_data->timeout);
J
Johannes Berg 已提交
4246

P
Paul Stewart 已提交
4247 4248 4249 4250 4251 4252 4253 4254 4255 4256
	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 已提交
4257 4258
		sdata_info(sdata, "associating with AP with corrupt %s\n",
			   corrupt_type);
P
Paul Stewart 已提交
4259 4260
	}

4261
	return 0;
J
Johannes Berg 已提交
4262
 err_clear:
4263 4264
	memset(ifmgd->bssid, 0, ETH_ALEN);
	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
J
Johannes Berg 已提交
4265 4266 4267 4268
	ifmgd->assoc_data = NULL;
 err_free:
	kfree(assoc_data);
	return err;
4269 4270
}

4271
int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4272
			 struct cfg80211_deauth_request *req)
4273
{
4274
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
4275
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
4276
	bool tx = !req->local_state_change;
4277
	bool report_frame = false;
4278

J
Johannes Berg 已提交
4279 4280 4281
	sdata_info(sdata,
		   "deauthenticating from %pM by local choice (reason=%d)\n",
		   req->bssid, req->reason_code);
4282

4283
	if (ifmgd->auth_data) {
4284
		drv_mgd_prepare_tx(sdata->local, sdata);
4285 4286
		ieee80211_send_deauth_disassoc(sdata, req->bssid,
					       IEEE80211_STYPE_DEAUTH,
4287
					       req->reason_code, tx,
4288
					       frame_buf);
4289 4290
		ieee80211_destroy_auth_data(sdata, false);

4291
		report_frame = true;
4292
		goto out;
4293 4294
	}

4295 4296 4297 4298
	if (ifmgd->associated &&
	    ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
				       req->reason_code, tx, frame_buf);
4299
		report_frame = true;
4300
	}
4301

4302
 out:
4303
	if (report_frame)
4304 4305
		cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
				      IEEE80211_DEAUTH_FRAME_LEN);
4306

4307 4308
	return 0;
}
4309

4310
int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
4311
			   struct cfg80211_disassoc_request *req)
J
Johannes Berg 已提交
4312
{
4313
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
4314
	u8 bssid[ETH_ALEN];
4315
	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
J
Johannes Berg 已提交
4316

J
Johannes Berg 已提交
4317 4318 4319 4320 4321 4322
	/*
	 * 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.
	 */
4323
	if (ifmgd->associated != req->bss)
4324 4325
		return -ENOLINK;

J
Johannes Berg 已提交
4326 4327 4328
	sdata_info(sdata,
		   "disassociating from %pM by local choice (reason=%d)\n",
		   req->bss->bssid, req->reason_code);
4329

4330
	memcpy(bssid, req->bss->bssid, ETH_ALEN);
4331 4332 4333
	ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
			       req->reason_code, !req->local_state_change,
			       frame_buf);
4334

4335 4336
	cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
			      IEEE80211_DEAUTH_FRAME_LEN);
4337

4338 4339
	return 0;
}
4340

4341
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
4342 4343 4344
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355
	/*
	 * 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);

4356
	sdata_lock(sdata);
4357 4358
	if (ifmgd->assoc_data) {
		struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
4359
		ieee80211_destroy_assoc_data(sdata, false);
4360 4361
		cfg80211_assoc_timeout(sdata->dev, bss);
	}
4362 4363 4364
	if (ifmgd->auth_data)
		ieee80211_destroy_auth_data(sdata, false);
	del_timer_sync(&ifmgd->timer);
4365
	sdata_unlock(sdata);
4366 4367
}

4368 4369 4370 4371 4372 4373
void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
			       enum nl80211_cqm_rssi_threshold_event rssi_event,
			       gfp_t gfp)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);

J
Johannes Berg 已提交
4374 4375
	trace_api_cqm_rssi_notify(sdata, rssi_event);

4376 4377 4378
	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
}
EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);