All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

mlme.c 62.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/rtnetlink.h>
20
#include <linux/pm_qos_params.h>
21
#include <linux/crc32.h>
22
#include <net/mac80211.h>
23
#include <asm/unaligned.h>
Johannes Berg's avatar
Johannes Berg committed
24

25
#include "ieee80211_i.h"
26
#include "driver-ops.h"
Johannes Berg's avatar
Johannes Berg committed
27 28
#include "rate.h"
#include "led.h"
29 30 31 32 33 34

#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_MAX_TRIES 3
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_MAX_TRIES 3
#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
35
#define IEEE80211_PROBE_WAIT (HZ / 5)
36

37 38 39
#define TMR_RUNNING_TIMER	0
#define TMR_RUNNING_CHANSW	1

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
/*
 * All cfg80211 functions have to be called outside a locked
 * section so that they can acquire a lock themselves... This
 * is much simpler than queuing up things in cfg80211, but we
 * do need some indirection for that here.
 */
enum rx_mgmt_action {
	/* no action required */
	RX_MGMT_NONE,

	/* caller must call cfg80211_send_rx_auth() */
	RX_MGMT_CFG80211_AUTH,

	/* caller must call cfg80211_send_rx_assoc() */
	RX_MGMT_CFG80211_ASSOC,

	/* caller must call cfg80211_send_deauth() */
	RX_MGMT_CFG80211_DEAUTH,

	/* caller must call cfg80211_send_disassoc() */
	RX_MGMT_CFG80211_DISASSOC,

	/* caller must call cfg80211_auth_timeout() & free work */
	RX_MGMT_CFG80211_AUTH_TO,

	/* caller must call cfg80211_assoc_timeout() & free work */
	RX_MGMT_CFG80211_ASSOC_TO,
};

69
/* utils */
70 71 72 73 74
static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
{
	WARN_ON(!mutex_is_locked(&ifmgd->mtx));
}

75
static int ecw2cw(int ecw)
Johannes Berg's avatar
Johannes Berg committed
76
{
77
	return (1 << ecw) - 1;
Johannes Berg's avatar
Johannes Berg committed
78 79
}

80
static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
81
				      struct ieee80211_supported_band *sband,
82
				      u32 *rates)
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
{
	int i, j, count;
	*rates = 0;
	count = 0;
	for (i = 0; i < bss->supp_rates_len; i++) {
		int rate = (bss->supp_rates[i] & 0x7F) * 5;

		for (j = 0; j < sband->n_bitrates; j++)
			if (sband->bitrates[j].bitrate == rate) {
				*rates |= BIT(j);
				count++;
				break;
			}
	}

	return count;
}

101 102 103 104 105 106 107
/*
 * ieee80211_enable_ht should be called only after the operating band
 * has been determined as ht configuration depends on the hw's
 * HT abilities for a specific band.
 */
static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
			       struct ieee80211_ht_info *hti,
108
			       const u8 *bssid, u16 ap_ht_cap_flags)
109 110 111 112 113
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_supported_band *sband;
	struct sta_info *sta;
	u32 changed = 0;
114
	u16 ht_opmode;
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
	bool enable_ht = true, ht_changed;
	enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;

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

	/* HT is not supported */
	if (!sband->ht_cap.ht_supported)
		enable_ht = false;

	/* check that channel matches the right operating channel */
	if (local->hw.conf.channel->center_freq !=
	    ieee80211_channel_to_frequency(hti->control_chan))
		enable_ht = false;

	if (enable_ht) {
		channel_type = NL80211_CHAN_HT20;

		if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
		    (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
		    (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
			switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
137 138 139
				if (!(local->hw.conf.channel->flags &
				    IEEE80211_CHAN_NO_HT40PLUS))
					channel_type = NL80211_CHAN_HT40PLUS;
140 141
				break;
			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
142 143 144
				if (!(local->hw.conf.channel->flags &
				    IEEE80211_CHAN_NO_HT40MINUS))
					channel_type = NL80211_CHAN_HT40MINUS;
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
				break;
			}
		}
	}

	ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
		     channel_type != local->hw.conf.channel_type;

	local->oper_channel_type = channel_type;

	if (ht_changed) {
                /* channel_type change automatically detected */
		ieee80211_hw_config(local, 0);

		rcu_read_lock();
160
		sta = sta_info_get(local, bssid);
161 162 163 164 165 166 167 168 169 170
		if (sta)
			rate_control_rate_update(local, sband, sta,
						 IEEE80211_RC_HT_CHANGED);
		rcu_read_unlock();
        }

	/* disable HT */
	if (!enable_ht)
		return 0;

171
	ht_opmode = le16_to_cpu(hti->operation_mode);
172 173

	/* if bss configuration changed store the new one */
174 175
	if (!sdata->ht_opmode_valid ||
	    sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
176
		changed |= BSS_CHANGED_HT;
177
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
178
		sdata->ht_opmode_valid = true;
179 180 181 182 183
	}

	return changed;
}

184 185
/* frame sending functions */

186 187
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
				 struct ieee80211_mgd_work *wk)
188
{
189
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
190 191 192
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
193 194
	u8 *pos;
	const u8 *ies, *ht_ie;
195 196 197 198
	int i, len, count, rates_len, supp_rates_len;
	u16 capab;
	int wmm = 0;
	struct ieee80211_supported_band *sband;
199
	u32 rates = 0;
200 201

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
202 203
			    sizeof(*mgmt) + 200 + wk->ie_len +
			    wk->ssid_len);
204 205 206 207 208 209 210 211 212
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
		       "frame\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

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

213
	capab = ifmgd->capab;
214 215 216 217 218 219 220 221

	if (local->hw.conf.channel->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;
	}

222 223 224 225
	if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
		capab |= WLAN_CAPABILITY_PRIVACY;
	if (wk->bss->wmm_used)
		wmm = 1;
226

227 228 229 230 231
	/* 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) */
	rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
232

233 234 235
	if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
	    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
		capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
236 237 238

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
239
	memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
240
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
241
	memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
242

243
	if (!is_zero_ether_addr(wk->prev_bssid)) {
244 245 246 247 248 249
		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);
250
		memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid,
251 252 253 254 255 256
		       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);
257
		mgmt->u.assoc_req.listen_interval =
258 259 260 261
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
262
	ies = pos = skb_put(skb, 2 + wk->ssid_len);
263
	*pos++ = WLAN_EID_SSID;
264 265
	*pos++ = wk->ssid_len;
	memcpy(pos, wk->ssid, wk->ssid_len);
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319

	/* add all rates which were marked to be used above */
	supp_rates_len = rates_len;
	if (supp_rates_len > 8)
		supp_rates_len = 8;

	len = sband->n_bitrates;
	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) {
			int rate = sband->bitrates[i].bitrate;
			*pos++ = (u8) (rate / 5);
			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) {
				int rate = sband->bitrates[i].bitrate;
				*pos++ = (u8) (rate / 5);
			}
		}
	}

	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 */
		*pos++ = local->hw.conf.channel->max_power; /* max tx power */

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

320 321 322
	if (wk->ie_len && wk->ie) {
		pos = skb_put(skb, wk->ie_len);
		memcpy(pos, wk->ie, wk->ie_len);
323 324
	}

325
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
326 327 328 329 330 331 332 333 334 335 336 337 338
		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++ = 0;
	}

	/* wmm support is a must to HT */
339 340 341 342 343 344
	/*
	 * 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.
	 */
345
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
346
	    sband->ht_cap.ht_supported &&
347
	    (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) &&
348
	    ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
349
	    (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
350 351 352
		struct ieee80211_ht_info *ht_info =
			(struct ieee80211_ht_info *)(ht_ie + 2);
		u16 cap = sband->ht_cap.cap;
353 354 355
		__le16 tmp;
		u32 flags = local->hw.conf.channel->flags;

356 357
		switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
358
			if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
359
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
360 361 362
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
363
		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
364
			if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
365
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
366 367 368 369 370 371 372 373 374 375 376 377 378
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
		}

		tmp = cpu_to_le16(cap);
		pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
		*pos++ = WLAN_EID_HT_CAPABILITY;
		*pos++ = sizeof(struct ieee80211_ht_cap);
		memset(pos, 0, sizeof(struct ieee80211_ht_cap));
		memcpy(pos, &tmp, sizeof(u16));
		pos += sizeof(u16);
		/* TODO: needs a define here for << 2 */
379 380 381
		*pos++ = sband->ht_cap.ampdu_factor |
			 (sband->ht_cap.ampdu_density << 2);
		memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
382 383
	}

384
	ieee80211_tx_skb(sdata, skb, 0);
385 386 387
}


388
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
Johannes Berg's avatar
Johannes Berg committed
389 390
					   const u8 *bssid, u16 stype, u16 reason,
					   void *cookie)
391 392
{
	struct ieee80211_local *local = sdata->local;
393
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
394 395
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
396

397
	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
398
	if (!skb) {
399 400
		printk(KERN_DEBUG "%s: failed to allocate buffer for "
		       "deauth/disassoc frame\n", sdata->dev->name);
401 402 403 404 405 406
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
407
	memcpy(mgmt->da, bssid, ETH_ALEN);
408
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
409
	memcpy(mgmt->bssid, bssid, ETH_ALEN);
410
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
411
	skb_put(skb, 2);
412
	/* u.deauth.reason_code == u.disassoc.reason_code */
413 414
	mgmt->u.deauth.reason_code = cpu_to_le16(reason);

415
	if (stype == IEEE80211_STYPE_DEAUTH)
Johannes Berg's avatar
Johannes Berg committed
416
		cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, cookie);
417
	else
Johannes Berg's avatar
Johannes Berg committed
418
		cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len, cookie);
419
	ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
420 421
}

422 423 424
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
425
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	struct ieee80211_pspoll *pspoll;
	struct sk_buff *skb;
	u16 fc;

	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for "
		       "pspoll frame\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
	memset(pspoll, 0, sizeof(*pspoll));
	fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM;
	pspoll->frame_control = cpu_to_le16(fc);
442
	pspoll->aid = cpu_to_le16(ifmgd->aid);
443 444 445 446

	/* aid in PS-Poll has its two MSBs each set to 1 */
	pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);

447
	memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
448 449 450 451 452
	memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);

	ieee80211_tx_skb(sdata, skb, 0);
}

453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
void ieee80211_send_nullfunc(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
			     int powersave)
{
	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 + 24);
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
		       "frame\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
	memset(nullfunc, 0, 24);
	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
			 IEEE80211_FCTL_TODS);
	if (powersave)
		fc |= cpu_to_le16(IEEE80211_FCTL_PM);
	nullfunc->frame_control = fc;
	memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
	memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
	memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);

	ieee80211_tx_skb(sdata, skb, 0);
}

486 487 488 489 490 491 492 493 494 495
/* 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);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

	if (!netif_running(sdata->dev))
		return;

496 497 498
	mutex_lock(&ifmgd->mtx);
	if (!ifmgd->associated)
		goto out;
499 500

	sdata->local->oper_channel = sdata->local->csa_channel;
501 502
	ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);

503
	/* XXX: shouldn't really modify cfg80211-owned data! */
504
	ifmgd->associated->cbss.channel = sdata->local->oper_channel;
505 506 507

	ieee80211_wake_queues_by_reason(&sdata->local->hw,
					IEEE80211_QUEUE_STOP_REASON_CSA);
508 509 510
 out:
	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
	mutex_unlock(&ifmgd->mtx);
511 512 513 514 515 516 517 518
}

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

519 520 521 522 523
	if (sdata->local->quiescing) {
		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
		return;
	}

524 525 526 527 528 529 530 531 532 533 534
	queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
}

void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
				      struct ieee80211_channel_sw_ie *sw_elem,
				      struct ieee80211_bss *bss)
{
	struct ieee80211_channel *new_ch;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);

535 536 537
	ASSERT_MGD_MTX(ifmgd);

	if (!ifmgd->associated)
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
		return;

	if (sdata->local->sw_scanning || sdata->local->hw_scanning)
		return;

	/* Disregard subsequent beacons if we are already running a timer
	   processing a CSA */

	if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
		return;

	new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
	if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED)
		return;

	sdata->local->csa_channel = new_ch;

	if (sw_elem->count <= 1) {
		queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
	} else {
		ieee80211_stop_queues_by_reason(&sdata->local->hw,
					IEEE80211_QUEUE_STOP_REASON_CSA);
		ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
		mod_timer(&ifmgd->chswitch_timer,
			  jiffies +
			  msecs_to_jiffies(sw_elem->count *
					   bss->cbss.beacon_interval));
	}
}

static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
					u16 capab_info, u8 *pwr_constr_elem,
					u8 pwr_constr_elem_len)
{
	struct ieee80211_conf *conf = &sdata->local->hw.conf;

	if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
		return;

	/* Power constraint IE length should be 1 octet */
	if (pwr_constr_elem_len != 1)
		return;

	if ((*pwr_constr_elem <= conf->channel->max_power) &&
	    (*pwr_constr_elem != sdata->local->power_constr_level)) {
		sdata->local->power_constr_level = *pwr_constr_elem;
		ieee80211_hw_config(sdata->local, 0);
	}
}

588 589 590 591 592 593
/* powersave */
static void ieee80211_enable_ps(struct ieee80211_local *local,
				struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_conf *conf = &local->hw.conf;

Johannes Berg's avatar
Johannes Berg committed
594 595 596 597 598 599 600
	/*
	 * If we are scanning right now then the parameters will
	 * take effect when scan finishes.
	 */
	if (local->hw_scanning || local->sw_scanning)
		return;

601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
	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);
		conf->flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}
}

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

/* need to hold RTNL or interface lock */
628
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
{
	struct ieee80211_sub_if_data *sdata, *found = NULL;
	int count = 0;

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

	list_for_each_entry(sdata, &local->interfaces, list) {
		if (!netif_running(sdata->dev))
			continue;
		if (sdata->vif.type != NL80211_IFTYPE_STATION)
			continue;
		found = sdata;
		count++;
	}

647
	if (count == 1 && found->u.mgd.powersave &&
648
	    found->u.mgd.associated && list_empty(&found->u.mgd.work_list) &&
649
	    !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) {
650 651 652 653 654 655 656 657
		s32 beaconint_us;

		if (latency < 0)
			latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);

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

658
		if (beaconint_us > latency) {
659
			local->ps_sdata = NULL;
660 661 662 663 664 665 666 667
		} else {
			u8 dtimper = found->vif.bss_conf.dtim_period;
			int maxslp = 1;

			if (dtimper > 1)
				maxslp = min_t(int, dtimper,
						    latency / beaconint_us);

668
			local->hw.conf.max_sleep_period = maxslp;
669
			local->ps_sdata = found;
670
		}
671
	} else {
672
		local->ps_sdata = NULL;
673
	}
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717

	ieee80211_change_ps(local);
}

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

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

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

	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
		ieee80211_send_nullfunc(local, sdata, 1);

	local->hw.conf.flags |= IEEE80211_CONF_PS;
	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}

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

718 719 720
	if (local->quiescing)
		return;

721 722 723
	queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
}

Johannes Berg's avatar
Johannes Berg committed
724
/* MLME */
725
static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
726
				     struct ieee80211_if_managed *ifmgd,
727 728 729 730 731 732 733
				     u8 *wmm_param, size_t wmm_param_len)
{
	struct ieee80211_tx_queue_params params;
	size_t left;
	int count;
	u8 *pos;

734
	if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
735 736 737 738 739
		return;

	if (!wmm_param)
		return;

740 741 742
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
		return;
	count = wmm_param[6] & 0x0f;
743
	if (count == ifmgd->wmm_last_param_set)
744
		return;
745
	ifmgd->wmm_last_param_set = count;
746 747 748 749 750 751 752 753 754 755 756 757 758

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

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

	local->wmm_acm = 0;
	for (; left >= 4; left -= 4, pos += 4) {
		int aci = (pos[0] >> 5) & 0x03;
		int acm = (pos[0] >> 4) & 0x01;
		int queue;

		switch (aci) {
759
		case 1: /* AC_BK */
Johannes Berg's avatar
Johannes Berg committed
760
			queue = 3;
Johannes Berg's avatar
Johannes Berg committed
761
			if (acm)
762
				local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
763
			break;
764
		case 2: /* AC_VI */
Johannes Berg's avatar
Johannes Berg committed
765
			queue = 1;
Johannes Berg's avatar
Johannes Berg committed
766
			if (acm)
767
				local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
768
			break;
769
		case 3: /* AC_VO */
Johannes Berg's avatar
Johannes Berg committed
770
			queue = 0;
Johannes Berg's avatar
Johannes Berg committed
771
			if (acm)
772
				local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
773
			break;
774
		case 0: /* AC_BE */
775
		default:
Johannes Berg's avatar
Johannes Berg committed
776
			queue = 2;
Johannes Berg's avatar
Johannes Berg committed
777
			if (acm)
778
				local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
779 780 781 782 783 784
			break;
		}

		params.aifs = pos[0] & 0x0f;
		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params.cw_min = ecw2cw(pos[1] & 0x0f);
785
		params.txop = get_unaligned_le16(pos + 2);
786
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
787
		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
788
		       "cWmin=%d cWmax=%d txop=%d\n",
789 790
		       wiphy_name(local->hw.wiphy), queue, aci, acm,
		       params.aifs, params.cw_min, params.cw_max, params.txop);
791
#endif
792
		if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx)
793
			printk(KERN_DEBUG "%s: failed to set TX queue "
794 795
			       "parameters for queue %d\n",
			       wiphy_name(local->hw.wiphy), queue);
796 797 798
	}
}

799 800
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
801
{
802
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
803
	u32 changed = 0;
804 805 806 807 808 809 810 811 812 813 814 815 816
	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);
817

818 819 820
	if (use_protection != bss_conf->use_cts_prot) {
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
821
	}
822

823 824
	if (use_short_preamble != bss_conf->use_short_preamble) {
		bss_conf->use_short_preamble = use_short_preamble;
825
		changed |= BSS_CHANGED_ERP_PREAMBLE;
826
	}
827

828 829 830
	if (use_short_slot != bss_conf->use_short_slot) {
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
831 832 833 834 835
	}

	return changed;
}

836
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
837
				     struct ieee80211_bss *bss,
Johannes Berg's avatar
Johannes Berg committed
838
				     u32 bss_info_changed)
839
{
840
	struct ieee80211_local *local = sdata->local;
841

Johannes Berg's avatar
Johannes Berg committed
842
	bss_info_changed |= BSS_CHANGED_ASSOC;
843 844 845 846
	/* set timing information */
	sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
	sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
	sdata->vif.bss_conf.dtim_period = bss->dtim_period;
847

848 849 850
	bss_info_changed |= BSS_CHANGED_BEACON_INT;
	bss_info_changed |= ieee80211_handle_bss_capability(sdata,
		bss->cbss.capability, bss->has_erp_value, bss->erp_value);
851

852 853
	sdata->u.mgd.associated = bss;
	memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
854

855
	ieee80211_led_assoc(local, 1);
856

857
	sdata->vif.bss_conf.assoc = 1;
858 859 860 861 862
	/*
	 * For now just always ask the driver to update the basic rateset
	 * when we have associated, we aren't checking whether it actually
	 * changed or not.
	 */
Johannes Berg's avatar
Johannes Berg committed
863
	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
864 865 866 867

	/* And the BSSID changed - we're associated now */
	bss_info_changed |= BSS_CHANGED_BSSID;

Johannes Berg's avatar
Johannes Berg committed
868
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
869

870
	/* will be same as sdata */
871 872 873 874 875
	if (local->ps_sdata) {
		mutex_lock(&local->iflist_mtx);
		ieee80211_recalc_ps(local, -1);
		mutex_unlock(&local->iflist_mtx);
	}
876

877 878
	netif_tx_start_all_queues(sdata->dev);
	netif_carrier_on(sdata->dev);
879 880
}

881 882 883
static enum rx_mgmt_action __must_check
ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
		       struct ieee80211_mgd_work *wk)
884
{
885
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
886
	struct ieee80211_local *local = sdata->local;
887

888 889
	wk->tries++;
	if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
890
		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
891
		       sdata->dev->name, wk->bss->cbss.bssid);
892 893 894

		/*
		 * Most likely AP is not in the range so remove the
895
		 * bss struct for that AP.
896
		 */
897
		cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
898 899 900

		/*
		 * We might have a pending scan which had no chance to run yet
901 902
		 * due to work needing to be done. Hence, queue the STAs work
		 * again for that.
903 904
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
905
		return RX_MGMT_CFG80211_AUTH_TO;
906 907
	}

908 909 910
	printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
			sdata->dev->name, wk->bss->cbss.bssid,
			wk->tries);
911

912 913
	/*
	 * Direct probe is sent to broadcast address as some APs
914 915
	 * will not answer to direct packet in unassociated state.
	 */
916 917 918 919
	ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0);

	wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
	mod_timer(&ifmgd->timer, wk->timeout);
920

921
	return RX_MGMT_NONE;
Johannes Berg's avatar
Johannes Berg committed
922
}
923

924

925 926 927
static enum rx_mgmt_action __must_check
ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
		       struct ieee80211_mgd_work *wk)
928
{
929
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
930
	struct ieee80211_local *local = sdata->local;
931

932 933
	wk->tries++;
	if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
934
		printk(KERN_DEBUG "%s: authentication with AP %pM"
935
		       " timed out\n",
936 937 938 939 940 941 942
		       sdata->dev->name, wk->bss->cbss.bssid);

		/*
		 * Most likely AP is not in the range so remove the
		 * bss struct for that AP.
		 */
		cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
943 944 945

		/*
		 * We might have a pending scan which had no chance to run yet
946 947
		 * due to work needing to be done. Hence, queue the STAs work
		 * again for that.
948 949
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
950
		return RX_MGMT_CFG80211_AUTH_TO;
951 952
	}

953 954 955 956 957 958
	printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
	       sdata->dev->name, wk->bss->cbss.bssid, wk->tries);

	ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
			    wk->bss->cbss.bssid, 0);
	wk->auth_transaction = 2;
959

960 961
	wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
	mod_timer(&ifmgd->timer, wk->timeout);
962

963
	return RX_MGMT_NONE;
964 965
}

966
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
967
				   const u8 *bssid, bool deauth)
968
{
969
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
970 971
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
972
	u32 changed = 0, config_changed = 0;
973

974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
	ASSERT_MGD_MTX(ifmgd);

	ifmgd->associated = NULL;
	memset(ifmgd->bssid, 0, ETH_ALEN);

	/*
	 * we need to commit the associated = NULL change because the
	 * scan code uses that to determine whether this iface should
	 * go to/wake up from powersave or not -- and could otherwise
	 * wake the queues erroneously.
	 */
	smp_mb();

	/*
	 * Thus, we can only afterwards stop the queues -- to account
	 * for the case where another CPU is finishing a scan at this
	 * time -- we don't want the scan code to enable queues.
	 */
992

993
	netif_tx_stop_all_queues(sdata->dev);
994 995
	netif_carrier_off(sdata->dev);

996
	rcu_read_lock();
997
	sta = sta_info_get(local, bssid);
998 999 1000
	if (sta)
		ieee80211_sta_tear_down_BA_sessions(sta);
	rcu_read_unlock();
1001

1002 1003 1004
	changed |= ieee80211_reset_erp_info(sdata);

	ieee80211_led_assoc(local, 0);
Johannes Berg's avatar
Johannes Berg committed
1005 1006
	changed |= BSS_CHANGED_ASSOC;
	sdata->vif.bss_conf.assoc = false;
1007

1008 1009
	ieee80211_set_wmm_default(sdata);

1010 1011
	ieee80211_recalc_idle(local);

1012
	/* channel(_type) changes are handled by ieee80211_hw_config */
Sujith's avatar
Sujith committed
1013
	local->oper_channel_type = NL80211_CHAN_NO_HT;
1014

1015 1016 1017
	/* on the next assoc, re-program HT parameters */
	sdata->ht_opmode_valid = false;

1018 1019
	local->power_constr_level = 0;

1020 1021 1022
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

1023 1024 1025 1026
	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		config_changed |= IEEE80211_CONF_CHANGE_PS;
	}
Johannes Berg's avatar
Johannes Berg committed
1027

1028
	ieee80211_hw_config(local, config_changed);
1029 1030 1031

	/* And the BSSID changed -- not very interesting here */
	changed |= BSS_CHANGED_BSSID;
Johannes Berg's avatar
Johannes Berg committed
1032
	ieee80211_bss_info_change_notify(sdata, changed);
1033 1034 1035

	rcu_read_lock();

1036
	sta = sta_info_get(local, bssid);
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	sta_info_unlink(&sta);

	rcu_read_unlock();

	sta_info_destroy(sta);
1047
}
1048

1049 1050 1051
static enum rx_mgmt_action __must_check
ieee80211_associate(struct ieee80211_sub_if_data *sdata,
		    struct ieee80211_mgd_work *wk)
1052
{
1053
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1054
	struct ieee80211_local *local = sdata->local;
1055

1056 1057
	wk->tries++;
	if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
1058
		printk(KERN_DEBUG "%s: association with AP %pM"
1059
		       " timed out\n",
1060 1061 1062 1063 1064 1065 1066 1067
		       sdata->dev->name, wk->bss->cbss.bssid);

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

1068 1069
		/*
		 * We might have a pending scan which had no chance to run yet
1070 1071
		 * due to work needing to be done. Hence, queue the STAs work
		 * again for that.
1072 1073
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
1074
		return RX_MGMT_CFG80211_ASSOC_TO;
1075 1076
	}

1077 1078 1079 1080 1081 1082
	printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
	       sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
	ieee80211_send_assoc(sdata, wk);

	wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
	mod_timer(&ifmgd->timer, wk->timeout);
1083

1084
	return RX_MGMT_NONE;
1085 1086
}

1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
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
	 * data idle periods for sending the periodical probe request to
	 * the AP.
	 */
	if (!is_multicast_ether_addr(hdr->addr1))
		mod_timer(&sdata->u.mgd.timer,
			  jiffies + IEEE80211_MONITORING_INTERVAL);
}
1102

1103 1104 1105 1106 1107 1108
void ieee80211_beacon_loss_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data,
			     u.mgd.beacon_loss_work);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;