mlme.c 64.7 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 <net/mac80211.h>
22
#include <asm/unaligned.h>
Johannes Berg's avatar
Johannes Berg committed
23

24
#include "ieee80211_i.h"
Johannes Berg's avatar
Johannes Berg committed
25 26
#include "rate.h"
#include "led.h"
27

28
#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2
29 30 31 32 33
#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)
34
#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
35 36
#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)

37 38
/* utils */
static int ecw2cw(int ecw)
Johannes Berg's avatar
Johannes Berg committed
39
{
40
	return (1 << ecw) - 1;
Johannes Berg's avatar
Johannes Berg committed
41 42
}

43
static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie)
44 45 46
{
	u8 *end, *pos;

47
	pos = bss->cbss.information_elements;
48 49
	if (pos == NULL)
		return NULL;
50
	end = pos + bss->cbss.len_information_elements;
51 52 53 54 55 56 57 58 59 60 61 62

	while (pos + 1 < end) {
		if (pos + 2 + pos[1] > end)
			break;
		if (pos[0] == ie)
			return pos;
		pos += 2 + pos[1];
	}

	return NULL;
}

63
static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
64
				      struct ieee80211_supported_band *sband,
65
				      u32 *rates)
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
{
	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;
}

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
/*
 * 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,
			       u16 ap_ht_cap_flags)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_supported_band *sband;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_bss_ht_conf ht;
	struct sta_info *sta;
	u32 changed = 0;
	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];

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

	/* 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:
				channel_type = NL80211_CHAN_HT40PLUS;
				break;
			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
				channel_type = NL80211_CHAN_HT40MINUS;
				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();

		sta = sta_info_get(local, ifmgd->bssid);
		if (sta)
			rate_control_rate_update(local, sband, sta,
						 IEEE80211_RC_HT_CHANGED);

		rcu_read_unlock();

        }

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

	ht.operation_mode = le16_to_cpu(hti->operation_mode);

	/* if bss configuration changed store the new one */
	if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) {
		changed |= BSS_CHANGED_HT;
		sdata->vif.bss_conf.ht = ht;
	}

	return changed;
}

167 168
/* frame sending functions */

169
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
170
{
171
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
172 173 174
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
175
	u8 *pos, *ies, *ht_ie;
176 177
	int i, len, count, rates_len, supp_rates_len;
	u16 capab;
178
	struct ieee80211_bss *bss;
179 180
	int wmm = 0;
	struct ieee80211_supported_band *sband;
181
	u32 rates = 0;
182 183

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
184
			    sizeof(*mgmt) + 200 + ifmgd->extra_ie_len +
185
			    ifmgd->ssid_len);
186 187 188 189 190 191 192 193 194
	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];

195
	capab = ifmgd->capab;
196 197 198 199 200 201 202 203

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

204
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
205
				   local->hw.conf.channel->center_freq,
206
				   ifmgd->ssid, ifmgd->ssid_len);
207
	if (bss) {
208
		if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
209 210 211 212 213 214 215 216 217 218
			capab |= WLAN_CAPABILITY_PRIVACY;
		if (bss->wmm_used)
			wmm = 1;

		/* 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(bss, sband, &rates);

219
		if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
220 221 222 223 224 225 226 227 228 229 230
		    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
			capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;

		ieee80211_rx_bss_put(local, bss);
	} else {
		rates = ~0;
		rates_len = sband->n_bitrates;
	}

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
231
	memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN);
232
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
233
	memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN);
234

235
	if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) {
236 237 238 239 240 241
		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);
242
		memcpy(mgmt->u.reassoc_req.current_ap, ifmgd->prev_bssid,
243 244 245 246 247 248
		       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);
249
		mgmt->u.assoc_req.listen_interval =
250 251 252 253
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
254
	ies = pos = skb_put(skb, 2 + ifmgd->ssid_len);
255
	*pos++ = WLAN_EID_SSID;
256 257
	*pos++ = ifmgd->ssid_len;
	memcpy(pos, ifmgd->ssid, ifmgd->ssid_len);
258 259 260 261 262 263 264 265 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

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

312 313 314
	if (ifmgd->extra_ie) {
		pos = skb_put(skb, ifmgd->extra_ie_len);
		memcpy(pos, ifmgd->extra_ie, ifmgd->extra_ie_len);
315 316
	}

317
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
318 319 320 321 322 323 324 325 326 327 328 329 330
		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 */
331 332 333 334 335 336
	/*
	 * 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.
	 */
337
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
338 339
	    sband->ht_cap.ht_supported &&
	    (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
340
	    ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
341
	    (!(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))) {
342 343 344
		struct ieee80211_ht_info *ht_info =
			(struct ieee80211_ht_info *)(ht_ie + 2);
		u16 cap = sband->ht_cap.cap;
345 346 347
		__le16 tmp;
		u32 flags = local->hw.conf.channel->flags;

348 349
		switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
350
			if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
351
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
352 353 354
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
355
		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
356
			if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
357
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
358 359 360 361 362 363 364 365 366 367 368 369 370
				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 */
371 372 373
		*pos++ = sband->ht_cap.ampdu_factor |
			 (sband->ht_cap.ampdu_density << 2);
		memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
374 375
	}

376 377 378 379 380
	kfree(ifmgd->assocreq_ies);
	ifmgd->assocreq_ies_len = (skb->data + skb->len) - ies;
	ifmgd->assocreq_ies = kmalloc(ifmgd->assocreq_ies_len, GFP_KERNEL);
	if (ifmgd->assocreq_ies)
		memcpy(ifmgd->assocreq_ies, ies, ifmgd->assocreq_ies_len);
381

382
	ieee80211_tx_skb(sdata, skb, 0);
383 384 385
}


386 387
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
					   u16 stype, u16 reason)
388 389
{
	struct ieee80211_local *local = sdata->local;
390
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
391 392
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
393

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

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

412 413 414 415
	if (stype == IEEE80211_STYPE_DEAUTH)
		cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, skb->len);
	else
		cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len);
416
	ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
417 418
}

419 420 421
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
422
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
	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);
439
	pspoll->aid = cpu_to_le16(ifmgd->aid);
440 441 442 443

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

444
	memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
445 446 447 448 449
	memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);

	ieee80211_tx_skb(sdata, skb, 0);
}

450 451 452 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 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
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);
}

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

	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) {
		if (!(local->ps_sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED))
			return;

		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 */
519
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
{
	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++;
	}

538 539 540 541 542 543 544 545 546 547 548 549 550 551
	if (count == 1 && found->u.mgd.powersave) {
		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);

		if (beaconint_us > latency)
			local->ps_sdata = NULL;
		else
			local->ps_sdata = found;
	} else {
552
		local->ps_sdata = NULL;
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 588 589 590 591 592 593 594 595 596 597 598 599 600

	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;

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

Johannes Berg's avatar
Johannes Berg committed
601
/* MLME */
602
static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
603
				     struct ieee80211_if_managed *ifmgd,
604 605 606 607 608 609 610
				     u8 *wmm_param, size_t wmm_param_len)
{
	struct ieee80211_tx_queue_params params;
	size_t left;
	int count;
	u8 *pos;

611
	if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
612 613 614 615 616
		return;

	if (!wmm_param)
		return;

617 618 619
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
		return;
	count = wmm_param[6] & 0x0f;
620
	if (count == ifmgd->wmm_last_param_set)
621
		return;
622
	ifmgd->wmm_last_param_set = count;
623 624 625 626 627 628 629 630 631 632 633 634 635

	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) {
636
		case 1: /* AC_BK */
Johannes Berg's avatar
Johannes Berg committed
637
			queue = 3;
Johannes Berg's avatar
Johannes Berg committed
638
			if (acm)
639
				local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
640
			break;
641
		case 2: /* AC_VI */
Johannes Berg's avatar
Johannes Berg committed
642
			queue = 1;
Johannes Berg's avatar
Johannes Berg committed
643
			if (acm)
644
				local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
645
			break;
646
		case 3: /* AC_VO */
Johannes Berg's avatar
Johannes Berg committed
647
			queue = 0;
Johannes Berg's avatar
Johannes Berg committed
648
			if (acm)
649
				local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
650
			break;
651
		case 0: /* AC_BE */
652
		default:
Johannes Berg's avatar
Johannes Berg committed
653
			queue = 2;
Johannes Berg's avatar
Johannes Berg committed
654
			if (acm)
655
				local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
656 657 658 659 660 661
			break;
		}

		params.aifs = pos[0] & 0x0f;
		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params.cw_min = ecw2cw(pos[1] & 0x0f);
662
		params.txop = get_unaligned_le16(pos + 2);
663
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
664
		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
665
		       "cWmin=%d cWmax=%d txop=%d\n",
666
		       local->mdev->name, queue, aci, acm, params.aifs, params.cw_min,
667 668
		       params.cw_max, params.txop);
#endif
669 670
		if (local->ops->conf_tx &&
		    local->ops->conf_tx(local_to_hw(local), queue, &params)) {
671
			printk(KERN_DEBUG "%s: failed to set TX queue "
672
			       "parameters for queue %d\n", local->mdev->name, queue);
673 674 675 676
		}
	}
}

677
static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid)
678 679 680 681 682
{
	u8 mask;
	u8 index, indexn1, indexn2;
	struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim;

683 684 685
	if (unlikely(!tim || elems->tim_len < 4))
		return false;

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
	aid &= 0x3fff;
	index = aid / 8;
	mask  = 1 << (aid & 7);

	indexn1 = tim->bitmap_ctrl & 0xfe;
	indexn2 = elems->tim_len + indexn1 - 4;

	if (index < indexn1 || index > indexn2)
		return false;

	index -= indexn1;

	return !!(tim->virtual_map[index] & mask);
}

701 702
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
703
{
704
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
705
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
706
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
707
#endif
708
	u32 changed = 0;
709 710 711 712 713 714 715 716 717 718 719 720 721
	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);
722

723
	if (use_protection != bss_conf->use_cts_prot) {
724
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
725
		if (net_ratelimit()) {
726
			printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n",
727
			       sdata->dev->name,
728
			       use_protection ? "enabled" : "disabled",
729
			       ifmgd->bssid);
730
		}
731
#endif
732 733
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
734
	}
735

736
	if (use_short_preamble != bss_conf->use_short_preamble) {
737
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
738 739
		if (net_ratelimit()) {
			printk(KERN_DEBUG "%s: switched to %s barker preamble"
740
			       " (BSSID=%pM)\n",
741
			       sdata->dev->name,
742
			       use_short_preamble ? "short" : "long",
743
			       ifmgd->bssid);
744
		}
745
#endif
746
		bss_conf->use_short_preamble = use_short_preamble;
747
		changed |= BSS_CHANGED_ERP_PREAMBLE;
748
	}
749

750 751 752
	if (use_short_slot != bss_conf->use_short_slot) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
		if (net_ratelimit()) {
753 754
			printk(KERN_DEBUG "%s: switched to %s slot time"
			       " (BSSID=%pM)\n",
755 756
			       sdata->dev->name,
			       use_short_slot ? "short" : "long",
757
			       ifmgd->bssid);
758 759 760 761
		}
#endif
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
762 763 764 765 766
	}

	return changed;
}

767
static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata)
768 769
{
	union iwreq_data wrqu;
770

771
	memset(&wrqu, 0, sizeof(wrqu));
772 773
	if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)
		memcpy(wrqu.ap_addr.sa_data, sdata->u.mgd.bssid, ETH_ALEN);
774 775 776 777
	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
	wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
}

778
static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata)
779
{
780
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
781 782 783
	char *buf;
	size_t len;
	int i;
784 785
	union iwreq_data wrqu;

786
	if (!ifmgd->assocreq_ies && !ifmgd->assocresp_ies)
787 788
		return;

789 790
	buf = kmalloc(50 + 2 * (ifmgd->assocreq_ies_len +
				ifmgd->assocresp_ies_len), GFP_KERNEL);
791 792 793 794
	if (!buf)
		return;

	len = sprintf(buf, "ASSOCINFO(");
795
	if (ifmgd->assocreq_ies) {
796
		len += sprintf(buf + len, "ReqIEs=");
797
		for (i = 0; i < ifmgd->assocreq_ies_len; i++) {
798
			len += sprintf(buf + len, "%02x",
799
				       ifmgd->assocreq_ies[i]);
800
		}
801
	}
802 803
	if (ifmgd->assocresp_ies) {
		if (ifmgd->assocreq_ies)
804 805
			len += sprintf(buf + len, " ");
		len += sprintf(buf + len, "RespIEs=");
806
		for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
807
			len += sprintf(buf + len, "%02x",
808
				       ifmgd->assocresp_ies[i]);
809
		}
810
	}
811 812 813 814
	len += sprintf(buf + len, ")");

	if (len > IW_CUSTOM_MAX) {
		len = sprintf(buf, "ASSOCRESPIE=");
815
		for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
816
			len += sprintf(buf + len, "%02x",
817
				       ifmgd->assocresp_ies[i]);
818 819 820
		}
	}

821 822 823 824 825
	if (len <= IW_CUSTOM_MAX) {
		memset(&wrqu, 0, sizeof(wrqu));
		wrqu.data.length = len;
		wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
	}
826 827

	kfree(buf);
828 829 830
}


831
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
Johannes Berg's avatar
Johannes Berg committed
832
				     u32 bss_info_changed)
833
{
834
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
835
	struct ieee80211_local *local = sdata->local;
Tomas Winkler's avatar
Tomas Winkler committed
836
	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
837

838
	struct ieee80211_bss *bss;
839

Johannes Berg's avatar
Johannes Berg committed
840
	bss_info_changed |= BSS_CHANGED_ASSOC;
841
	ifmgd->flags |= IEEE80211_STA_ASSOCIATED;
842

843
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
844
				   conf->channel->center_freq,
845
				   ifmgd->ssid, ifmgd->ssid_len);
846 847
	if (bss) {
		/* set timing information */
848 849
		sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
		sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
850
		sdata->vif.bss_conf.dtim_period = bss->dtim_period;
851

Johannes Berg's avatar
Johannes Berg committed
852
		bss_info_changed |= ieee80211_handle_bss_capability(sdata,
853
			bss->cbss.capability, bss->has_erp_value, bss->erp_value);
854

855 856
		cfg80211_hold_bss(&bss->cbss);

857
		ieee80211_rx_bss_put(local, bss);
858 859
	}

860 861 862
	ifmgd->flags |= IEEE80211_STA_PREV_BSSID_SET;
	memcpy(ifmgd->prev_bssid, sdata->u.mgd.bssid, ETH_ALEN);
	ieee80211_sta_send_associnfo(sdata);
863

864
	ifmgd->last_probe = jiffies;
865
	ieee80211_led_assoc(local, 1);
866

867
	sdata->vif.bss_conf.assoc = 1;
868 869 870 871 872
	/*
	 * 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
873 874
	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
875

876 877 878
	/* will be same as sdata */
	if (local->ps_sdata)
		ieee80211_enable_ps(local, sdata);
879

880 881
	netif_tx_start_all_queues(sdata->dev);
	netif_carrier_on(sdata->dev);
882

883
	ieee80211_sta_send_apinfo(sdata);
884 885
}

886
static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
887
{
888
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
889
	struct ieee80211_local *local = sdata->local;
890 891 892

	ifmgd->direct_probe_tries++;
	if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
893
		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
894 895 896
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_sta_send_apinfo(sdata);
897 898 899 900 901

		/*
		 * Most likely AP is not in the range so remove the
		 * bss information associated to the AP
		 */
902
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
903
				sdata->local->hw.conf.channel->center_freq,
904
				ifmgd->ssid, ifmgd->ssid_len);
905 906 907 908 909 910 911

		/*
		 * We might have a pending scan which had no chance to run yet
		 * due to state == IEEE80211_STA_MLME_DIRECT_PROBE.
		 * Hence, queue the STAs work again
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
912 913 914
		return;
	}

915
	printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n",
916 917
			sdata->dev->name, ifmgd->bssid,
			ifmgd->direct_probe_tries);
918

919
	ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
920

921
	set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifmgd->request);
922 923 924 925 926

	/* 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,
927
				 ifmgd->ssid, ifmgd->ssid_len, NULL, 0);
928

929
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
Johannes Berg's avatar
Johannes Berg committed
930
}
931

932

933
static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
934
{
935
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
936
	struct ieee80211_local *local = sdata->local;
937 938
	u8 *ies;
	size_t ies_len;
939 940 941

	ifmgd->auth_tries++;
	if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
942
		printk(KERN_DEBUG "%s: authentication with AP %pM"
943
		       " timed out\n",
944 945 946 947
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_sta_send_apinfo(sdata);
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
948
				sdata->local->hw.conf.channel->center_freq,
949
				ifmgd->ssid, ifmgd->ssid_len);
950 951 952 953 954 955 956

		/*
		 * We might have a pending scan which had no chance to run yet
		 * due to state == IEEE80211_STA_MLME_AUTHENTICATE.
		 * Hence, queue the STAs work again
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
957 958 959
		return;
	}

960
	ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
961
	printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
962
	       sdata->dev->name, ifmgd->bssid);
963

964 965 966 967 968 969 970 971
	if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
		ies = ifmgd->sme_auth_ie;
		ies_len = ifmgd->sme_auth_ie_len;
	} else {
		ies = NULL;
		ies_len = 0;
	}
	ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ies, ies_len,
972 973
			    ifmgd->bssid, 0);
	ifmgd->auth_transaction = 2;
974

975
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
976 977
}

978 979 980 981
/*
 * The disassoc 'reason' argument can be either our own reason
 * if self disconnected or a reason code from the AP.
 */
982
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
983 984
				   bool deauth, bool self_disconnected,
				   u16 reason)
985
{
986
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
987
	struct ieee80211_local *local = sdata->local;
988 989
	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
	struct ieee80211_bss *bss;
990
	struct sta_info *sta;
991
	u32 changed = 0, config_changed = 0;
992 993 994

	rcu_read_lock();

995
	sta = sta_info_get(local, ifmgd->bssid);
996 997 998 999 1000 1001
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	if (deauth) {
1002 1003
		ifmgd->direct_probe_tries = 0;
		ifmgd->auth_tries = 0;
1004
	}
1005 1006
	ifmgd->assoc_scan_tries = 0;
	ifmgd->assoc_tries = 0;
1007

1008
	netif_tx_stop_all_queues(sdata->dev);
1009 1010
	netif_carrier_off(sdata->dev);

1011
	ieee80211_sta_tear_down_BA_sessions(sta);
1012

1013 1014 1015 1016 1017 1018 1019 1020 1021
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
				   conf->channel->center_freq,
				   ifmgd->ssid, ifmgd->ssid_len);

	if (bss) {
		cfg80211_unhold_bss(&bss->cbss);
		ieee80211_rx_bss_put(local, bss);
	}

1022 1023
	if (self_disconnected) {
		if (deauth)
1024 1025
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DEAUTH, reason);
1026
		else
1027 1028
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DISASSOC, reason);
1029 1030
	}

1031
	ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
1032 1033 1034
	changed |= ieee80211_reset_erp_info(sdata);

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

1038
	ieee80211_sta_send_apinfo(sdata);
1039

1040
	if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
1041 1042
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,