mlme.c 58.0 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 <net/mac80211.h>
21
#include <asm/unaligned.h>
J
Johannes Berg 已提交
22

23
#include "ieee80211_i.h"
J
Johannes Berg 已提交
24 25
#include "rate.h"
#include "led.h"
26

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

36 37
/* utils */
static int ecw2cw(int ecw)
J
Johannes Berg 已提交
38
{
39
	return (1 << ecw) - 1;
J
Johannes Berg 已提交
40 41
}

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

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

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

	return NULL;
}

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

J
Johannes Berg 已提交
83 84
/* frame sending functions */

85 86 87 88 89 90
static void add_extra_ies(struct sk_buff *skb, u8 *ies, size_t ies_len)
{
	if (ies)
		memcpy(skb_put(skb, ies_len), ies, ies_len);
}

91
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
92
{
93
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
94 95 96
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
97
	u8 *pos, *ies, *ht_ie, *e_ies;
98 99
	int i, len, count, rates_len, supp_rates_len;
	u16 capab;
100
	struct ieee80211_bss *bss;
101 102
	int wmm = 0;
	struct ieee80211_supported_band *sband;
103
	u32 rates = 0;
104 105
	size_t e_ies_len;

106
	if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) {
107 108
		e_ies = sdata->u.mgd.ie_reassocreq;
		e_ies_len = sdata->u.mgd.ie_reassocreq_len;
109
	} else {
110 111
		e_ies = sdata->u.mgd.ie_assocreq;
		e_ies_len = sdata->u.mgd.ie_assocreq_len;
112
	}
113 114

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
115 116
			    sizeof(*mgmt) + 200 + ifmgd->extra_ie_len +
			    ifmgd->ssid_len + e_ies_len);
117 118 119 120 121 122 123 124 125
	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];

126
	capab = ifmgd->capab;
127 128 129 130 131 132 133 134

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

135
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
136
				   local->hw.conf.channel->center_freq,
137
				   ifmgd->ssid, ifmgd->ssid_len);
138
	if (bss) {
139
		if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
140 141 142 143 144 145 146 147 148 149
			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);

150
		if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
151 152 153 154 155 156 157 158 159 160 161
		    (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);
162
	memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN);
163
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
164
	memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN);
165

166
	if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) {
167 168 169 170 171 172
		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);
173
		memcpy(mgmt->u.reassoc_req.current_ap, ifmgd->prev_bssid,
174 175 176 177 178 179
		       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);
180
		mgmt->u.assoc_req.listen_interval =
181 182 183 184
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
185
	ies = pos = skb_put(skb, 2 + ifmgd->ssid_len);
186
	*pos++ = WLAN_EID_SSID;
187 188
	*pos++ = ifmgd->ssid_len;
	memcpy(pos, ifmgd->ssid, ifmgd->ssid_len);
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 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 234 235 236 237 238 239 240 241 242

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

243 244 245
	if (ifmgd->extra_ie) {
		pos = skb_put(skb, ifmgd->extra_ie_len);
		memcpy(pos, ifmgd->extra_ie, ifmgd->extra_ie_len);
246 247
	}

248
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
249 250 251 252 253 254 255 256 257 258 259 260 261
		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 */
262 263 264 265 266 267
	/*
	 * 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.
	 */
268
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
J
Johannes Berg 已提交
269 270
	    sband->ht_cap.ht_supported &&
	    (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
271
	    ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
272
	    (!(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))) {
J
Johannes Berg 已提交
273 274 275
		struct ieee80211_ht_info *ht_info =
			(struct ieee80211_ht_info *)(ht_ie + 2);
		u16 cap = sband->ht_cap.cap;
276 277 278
		__le16 tmp;
		u32 flags = local->hw.conf.channel->flags;

J
Johannes Berg 已提交
279 280
		switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
281
			if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
J
Johannes Berg 已提交
282
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
283 284 285
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
J
Johannes Berg 已提交
286
		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
287
			if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
J
Johannes Berg 已提交
288
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
289 290 291 292 293 294 295 296 297 298 299 300 301
				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 */
J
Johannes Berg 已提交
302 303 304
		*pos++ = sband->ht_cap.ampdu_factor |
			 (sband->ht_cap.ampdu_density << 2);
		memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
305 306
	}

307 308
	add_extra_ies(skb, e_ies, e_ies_len);

309 310 311 312 313
	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);
314

J
Johannes Berg 已提交
315
	ieee80211_tx_skb(sdata, skb, 0);
316 317 318
}


319 320
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
					   u16 stype, u16 reason)
321 322
{
	struct ieee80211_local *local = sdata->local;
323
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
324 325
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
326 327
	u8 *ies;
	size_t ies_len;
328

329
	if (stype == IEEE80211_STYPE_DEAUTH) {
330 331
		ies = sdata->u.mgd.ie_deauth;
		ies_len = sdata->u.mgd.ie_deauth_len;
332
	} else {
333 334
		ies = sdata->u.mgd.ie_disassoc;
		ies_len = sdata->u.mgd.ie_disassoc_len;
335 336 337 338
	}

	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) +
			    ies_len);
339
	if (!skb) {
340 341
		printk(KERN_DEBUG "%s: failed to allocate buffer for "
		       "deauth/disassoc frame\n", sdata->dev->name);
342 343 344 345 346 347
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
348
	memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN);
349
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
350
	memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN);
351
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
352
	skb_put(skb, 2);
353
	/* u.deauth.reason_code == u.disassoc.reason_code */
354 355
	mgmt->u.deauth.reason_code = cpu_to_le16(reason);

356 357
	add_extra_ies(skb, ies, ies_len);

358
	ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
359 360
}

361 362 363
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
364
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
	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);
381
	pspoll->aid = cpu_to_le16(ifmgd->aid);
382 383 384 385

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

386
	memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
387 388 389 390 391
	memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);

	ieee80211_tx_skb(sdata, skb, 0);
}

J
Johannes Berg 已提交
392
/* MLME */
393
static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
394
				     struct ieee80211_if_managed *ifmgd,
395 396 397 398 399 400 401
				     u8 *wmm_param, size_t wmm_param_len)
{
	struct ieee80211_tx_queue_params params;
	size_t left;
	int count;
	u8 *pos;

402
	if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
403 404 405 406 407
		return;

	if (!wmm_param)
		return;

408 409 410
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
		return;
	count = wmm_param[6] & 0x0f;
411
	if (count == ifmgd->wmm_last_param_set)
412
		return;
413
	ifmgd->wmm_last_param_set = count;
414 415 416 417 418 419 420 421 422 423 424 425 426

	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) {
427
		case 1: /* AC_BK */
J
Johannes Berg 已提交
428
			queue = 3;
J
Johannes Berg 已提交
429
			if (acm)
430
				local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
431
			break;
432
		case 2: /* AC_VI */
J
Johannes Berg 已提交
433
			queue = 1;
J
Johannes Berg 已提交
434
			if (acm)
435
				local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
436
			break;
437
		case 3: /* AC_VO */
J
Johannes Berg 已提交
438
			queue = 0;
J
Johannes Berg 已提交
439
			if (acm)
440
				local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
441
			break;
442
		case 0: /* AC_BE */
443
		default:
J
Johannes Berg 已提交
444
			queue = 2;
J
Johannes Berg 已提交
445
			if (acm)
446
				local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
447 448 449 450 451 452
			break;
		}

		params.aifs = pos[0] & 0x0f;
		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params.cw_min = ecw2cw(pos[1] & 0x0f);
453
		params.txop = get_unaligned_le16(pos + 2);
454
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
455
		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
456
		       "cWmin=%d cWmax=%d txop=%d\n",
457
		       local->mdev->name, queue, aci, acm, params.aifs, params.cw_min,
458 459
		       params.cw_max, params.txop);
#endif
460 461
		if (local->ops->conf_tx &&
		    local->ops->conf_tx(local_to_hw(local), queue, &params)) {
462
			printk(KERN_DEBUG "%s: failed to set TX queue "
463
			       "parameters for queue %d\n", local->mdev->name, queue);
464 465 466 467
		}
	}
}

468
static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid)
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
{
	u8 mask;
	u8 index, indexn1, indexn2;
	struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim;

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

J
Johannes Berg 已提交
489 490
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
491
{
J
Johannes Berg 已提交
492
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
493
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
494
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
495
#endif
496
	u32 changed = 0;
J
Johannes Berg 已提交
497 498 499 500 501 502 503 504 505 506 507 508 509
	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);
510

511
	if (use_protection != bss_conf->use_cts_prot) {
512
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
513
		if (net_ratelimit()) {
514
			printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n",
515
			       sdata->dev->name,
516
			       use_protection ? "enabled" : "disabled",
517
			       ifmgd->bssid);
518
		}
519
#endif
520 521
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
522
	}
523

524
	if (use_short_preamble != bss_conf->use_short_preamble) {
525
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
526 527
		if (net_ratelimit()) {
			printk(KERN_DEBUG "%s: switched to %s barker preamble"
528
			       " (BSSID=%pM)\n",
529
			       sdata->dev->name,
530
			       use_short_preamble ? "short" : "long",
531
			       ifmgd->bssid);
532
		}
533
#endif
534
		bss_conf->use_short_preamble = use_short_preamble;
535
		changed |= BSS_CHANGED_ERP_PREAMBLE;
536
	}
537

J
Johannes Berg 已提交
538 539 540
	if (use_short_slot != bss_conf->use_short_slot) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
		if (net_ratelimit()) {
541 542
			printk(KERN_DEBUG "%s: switched to %s slot time"
			       " (BSSID=%pM)\n",
J
Johannes Berg 已提交
543 544
			       sdata->dev->name,
			       use_short_slot ? "short" : "long",
545
			       ifmgd->bssid);
J
Johannes Berg 已提交
546 547 548 549
		}
#endif
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
550 551 552 553 554
	}

	return changed;
}

555
static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata)
556 557
{
	union iwreq_data wrqu;
558

559
	memset(&wrqu, 0, sizeof(wrqu));
560 561
	if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)
		memcpy(wrqu.ap_addr.sa_data, sdata->u.mgd.bssid, ETH_ALEN);
562 563 564 565
	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
	wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
}

566
static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata)
567
{
568
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
569 570 571
	char *buf;
	size_t len;
	int i;
572 573
	union iwreq_data wrqu;

574
	if (!ifmgd->assocreq_ies && !ifmgd->assocresp_ies)
575 576
		return;

577 578
	buf = kmalloc(50 + 2 * (ifmgd->assocreq_ies_len +
				ifmgd->assocresp_ies_len), GFP_KERNEL);
579 580 581 582
	if (!buf)
		return;

	len = sprintf(buf, "ASSOCINFO(");
583
	if (ifmgd->assocreq_ies) {
584
		len += sprintf(buf + len, "ReqIEs=");
585
		for (i = 0; i < ifmgd->assocreq_ies_len; i++) {
586
			len += sprintf(buf + len, "%02x",
587
				       ifmgd->assocreq_ies[i]);
588
		}
589
	}
590 591
	if (ifmgd->assocresp_ies) {
		if (ifmgd->assocreq_ies)
592 593
			len += sprintf(buf + len, " ");
		len += sprintf(buf + len, "RespIEs=");
594
		for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
595
			len += sprintf(buf + len, "%02x",
596
				       ifmgd->assocresp_ies[i]);
597
		}
598
	}
599 600 601 602
	len += sprintf(buf + len, ")");

	if (len > IW_CUSTOM_MAX) {
		len = sprintf(buf, "ASSOCRESPIE=");
603
		for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
604
			len += sprintf(buf + len, "%02x",
605
				       ifmgd->assocresp_ies[i]);
606 607 608
		}
	}

609 610 611 612 613
	if (len <= IW_CUSTOM_MAX) {
		memset(&wrqu, 0, sizeof(wrqu));
		wrqu.data.length = len;
		wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
	}
614 615

	kfree(buf);
616 617 618
}


619
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
620
				     u32 bss_info_changed)
621
{
622
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
623
	struct ieee80211_local *local = sdata->local;
T
Tomas Winkler 已提交
624
	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
625

626
	struct ieee80211_bss *bss;
627

J
Johannes Berg 已提交
628
	bss_info_changed |= BSS_CHANGED_ASSOC;
629
	ifmgd->flags |= IEEE80211_STA_ASSOCIATED;
630

631
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
632
				   conf->channel->center_freq,
633
				   ifmgd->ssid, ifmgd->ssid_len);
634 635
	if (bss) {
		/* set timing information */
636 637
		sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
		sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
J
Johannes Berg 已提交
638
		sdata->vif.bss_conf.dtim_period = bss->dtim_period;
639

J
Johannes Berg 已提交
640
		bss_info_changed |= ieee80211_handle_bss_capability(sdata,
641
			bss->cbss.capability, bss->has_erp_value, bss->erp_value);
642 643

		ieee80211_rx_bss_put(local, bss);
644 645
	}

646 647 648
	ifmgd->flags |= IEEE80211_STA_PREV_BSSID_SET;
	memcpy(ifmgd->prev_bssid, sdata->u.mgd.bssid, ETH_ALEN);
	ieee80211_sta_send_associnfo(sdata);
649

650
	ifmgd->last_probe = jiffies;
651
	ieee80211_led_assoc(local, 1);
652

J
Johannes Berg 已提交
653
	sdata->vif.bss_conf.assoc = 1;
654 655 656 657 658
	/*
	 * 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.
	 */
J
Johannes Berg 已提交
659 660
	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
661

662 663 664
	if (local->powersave) {
		if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) &&
		    local->hw.conf.dynamic_ps_timeout > 0) {
665
			mod_timer(&local->dynamic_ps_timer, jiffies +
666 667
				  msecs_to_jiffies(
					local->hw.conf.dynamic_ps_timeout));
668 669 670
		} else {
			if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
				ieee80211_send_nullfunc(local, sdata, 1);
671
			conf->flags |= IEEE80211_CONF_PS;
672
			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
673
		}
674 675
	}

676 677
	netif_tx_start_all_queues(sdata->dev);
	netif_carrier_on(sdata->dev);
678

679
	ieee80211_sta_send_apinfo(sdata);
680 681
}

682
static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
683
{
684
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
685
	struct ieee80211_local *local = sdata->local;
686 687 688

	ifmgd->direct_probe_tries++;
	if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
689
		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
690 691 692
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_sta_send_apinfo(sdata);
693 694 695 696 697

		/*
		 * Most likely AP is not in the range so remove the
		 * bss information associated to the AP
		 */
698
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
699
				sdata->local->hw.conf.channel->center_freq,
700
				ifmgd->ssid, ifmgd->ssid_len);
701 702 703 704 705 706 707

		/*
		 * 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);
708 709 710
		return;
	}

711
	printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n",
712 713
			sdata->dev->name, ifmgd->bssid,
			ifmgd->direct_probe_tries);
714

715
	ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
716

717
	set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifmgd->request);
718 719 720 721 722

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

725
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
J
Johannes Berg 已提交
726
}
727

728

729
static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
730
{
731
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
732
	struct ieee80211_local *local = sdata->local;
733 734
	u8 *ies;
	size_t ies_len;
735 736 737

	ifmgd->auth_tries++;
	if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
738
		printk(KERN_DEBUG "%s: authentication with AP %pM"
739
		       " timed out\n",
740 741 742 743
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_sta_send_apinfo(sdata);
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
744
				sdata->local->hw.conf.channel->center_freq,
745
				ifmgd->ssid, ifmgd->ssid_len);
746 747 748 749 750 751 752

		/*
		 * 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);
753 754 755
		return;
	}

756
	ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
757
	printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
758
	       sdata->dev->name, ifmgd->bssid);
759

760 761 762 763 764 765 766 767
	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,
768 769
			    ifmgd->bssid, 0);
	ifmgd->auth_transaction = 2;
770

771
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
772 773
}

774 775 776 777
/*
 * The disassoc 'reason' argument can be either our own reason
 * if self disconnected or a reason code from the AP.
 */
778
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
779 780
				   bool deauth, bool self_disconnected,
				   u16 reason)
781
{
782
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
783 784
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
785
	u32 changed = 0, config_changed = 0;
786 787 788

	rcu_read_lock();

789
	sta = sta_info_get(local, ifmgd->bssid);
790 791 792 793 794 795
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	if (deauth) {
796 797
		ifmgd->direct_probe_tries = 0;
		ifmgd->auth_tries = 0;
798
	}
799 800
	ifmgd->assoc_scan_tries = 0;
	ifmgd->assoc_tries = 0;
801

802
	netif_tx_stop_all_queues(sdata->dev);
803 804
	netif_carrier_off(sdata->dev);

805
	ieee80211_sta_tear_down_BA_sessions(sta);
806 807 808

	if (self_disconnected) {
		if (deauth)
809 810
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DEAUTH, reason);
811
		else
812 813
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DISASSOC, reason);
814 815
	}

816
	ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
817 818 819
	changed |= ieee80211_reset_erp_info(sdata);

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

823
	ieee80211_sta_send_apinfo(sdata);
824

825
	if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
826 827
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
828
				sdata->local->hw.conf.channel->center_freq,
829
				ifmgd->ssid, ifmgd->ssid_len);
830
	}
831 832 833

	rcu_read_unlock();

834
	/* channel(_type) changes are handled by ieee80211_hw_config */
S
Sujith 已提交
835
	local->oper_channel_type = NL80211_CHAN_NO_HT;
836

837 838
	local->power_constr_level = 0;

839 840 841
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

842 843 844 845
	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		config_changed |= IEEE80211_CONF_CHANGE_PS;
	}
J
Johannes Berg 已提交
846

847
	ieee80211_hw_config(local, config_changed);
J
Johannes Berg 已提交
848
	ieee80211_bss_info_change_notify(sdata, changed);
849 850 851

	rcu_read_lock();

852
	sta = sta_info_get(local, ifmgd->bssid);
853 854 855 856 857 858 859 860 861 862
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	sta_info_unlink(&sta);

	rcu_read_unlock();

	sta_info_destroy(sta);
863
}
864

865 866 867 868 869 870 871 872
static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
{
	if (!sdata || !sdata->default_key ||
	    sdata->default_key->conf.alg != ALG_WEP)
		return 0;
	return 1;
}

873
static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata)
874
{
875
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
876
	struct ieee80211_local *local = sdata->local;
877
	struct ieee80211_bss *bss;
878 879 880
	int bss_privacy;
	int wep_privacy;
	int privacy_invoked;
881

882 883
	if (!ifmgd || (ifmgd->flags & (IEEE80211_STA_MIXED_CELL |
				       IEEE80211_STA_EXT_SME)))
884 885
		return 0;

886
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
887
				   local->hw.conf.channel->center_freq,
888
				   ifmgd->ssid, ifmgd->ssid_len);
889 890 891
	if (!bss)
		return 0;

892
	bss_privacy = !!(bss->cbss.capability & WLAN_CAPABILITY_PRIVACY);
893
	wep_privacy = !!ieee80211_sta_wep_configured(sdata);
894
	privacy_invoked = !!(ifmgd->flags & IEEE80211_STA_PRIVACY_INVOKED);
895

896
	ieee80211_rx_bss_put(local, bss);
897

898 899 900 901
	if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
		return 0;

	return 1;
902 903
}

904
static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
905
{
906
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
907
	struct ieee80211_local *local = sdata->local;
908 909 910

	ifmgd->assoc_tries++;
	if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
911
		printk(KERN_DEBUG "%s: association with AP %pM"
912
		       " timed out\n",
913 914 915 916
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_sta_send_apinfo(sdata);
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
917
				sdata->local->hw.conf.channel->center_freq,
918
				ifmgd->ssid, ifmgd->ssid_len);
919 920 921 922 923 924
		/*
		 * We might have a pending scan which had no chance to run yet
		 * due to state == IEEE80211_STA_MLME_ASSOCIATE.
		 * Hence, queue the STAs work again
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
925 926 927
		return;
	}

928
	ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
929
	printk(KERN_DEBUG "%s: associate with AP %pM\n",
930 931
	       sdata->dev->name, ifmgd->bssid);
	if (ieee80211_privacy_mismatch(sdata)) {
932
		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
933
		       "mixed-cell disabled - abort association\n", sdata->dev->name);
934
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
935 936 937
		return;
	}

938
	ieee80211_send_assoc(sdata);
939

940
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
941 942 943
}


944
static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
945
{
946
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
947
	struct ieee80211_local *local = sdata->local;
948 949 950 951 952 953 954 955
	struct sta_info *sta;
	int disassoc;

	/* TODO: start monitoring current AP signal quality and number of
	 * missed beacons. Scan other channels every now and then and search
	 * for better APs. */
	/* TODO: remove expired BSSes */

956
	ifmgd->state = IEEE80211_STA_MLME_ASSOCIATED;
957

958 959
	rcu_read_lock();

960
	sta = sta_info_get(local, ifmgd->bssid);
961
	if (!sta) {
962
		printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
963
		       sdata->dev->name, ifmgd->bssid);
964 965 966 967 968
		disassoc = 1;
	} else {
		disassoc = 0;
		if (time_after(jiffies,
			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
969
			if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
970
				printk(KERN_DEBUG "%s: No ProbeResp from "
971
				       "current AP %pM - assume out of "
972
				       "range\n",
973
				       sdata->dev->name, ifmgd->bssid);
974
				disassoc = 1;
975
			} else
976 977
				ieee80211_send_probe_req(sdata, ifmgd->bssid,
							 ifmgd->ssid,
978 979
							 ifmgd->ssid_len,
							 NULL, 0);
980
			ifmgd->flags ^= IEEE80211_STA_PROBEREQ_POLL;
981
		} else {
982 983
			ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
			if (time_after(jiffies, ifmgd->last_probe +
984
				       IEEE80211_PROBE_INTERVAL)) {
985 986 987
				ifmgd->last_probe = jiffies;
				ieee80211_send_probe_req(sdata, ifmgd->bssid,
							 ifmgd->ssid,
988 989
							 ifmgd->ssid_len,
							 NULL, 0);
990 991 992
			}
		}
	}
993 994 995

	rcu_read_unlock();

996
	if (disassoc)
997
		ieee80211_set_disassoc(sdata, true, true,
J
Johannes Berg 已提交
998
					WLAN_REASON_PREV_AUTH_NOT_VALID);
999
	else
1000
		mod_timer(&ifmgd->timer, jiffies +
J
Johannes Berg 已提交
1001
				      IEEE80211_MONITORING_INTERVAL);
1002 1003 1004
}


1005
static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata)
1006
{
1007 1008
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

1009
	printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
1010
	ifmgd->flags |= IEEE80211_STA_AUTHENTICATED;
1011 1012 1013 1014 1015
	if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
		/* Wait for SME to request association */
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
	} else
		ieee80211_associate(sdata);
1016 1017 1018
}


1019
static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1020 1021 1022 1023 1024 1025 1026
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u8 *pos;
	struct ieee802_11_elems elems;

	pos = mgmt->u.auth.variable;
1027
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1028
	if (!elems.challenge)
1029
		return;
1030 1031 1032 1033
	ieee80211_send_auth(sdata, 3, sdata->u.mgd.auth_alg,
			    elems.challenge - 2, elems.challenge_len + 2,
			    sdata->u.mgd.bssid, 1);
	sdata->u.mgd.auth_transaction = 4;
1034 1035
}

1036
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1037 1038 1039
				   struct ieee80211_mgmt *mgmt,
				   size_t len)
{
1040
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1041 1042
	u16 auth_alg, auth_transaction, status_code;

1043
	if (ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE)
1044 1045
		return;

1046
	if (len < 24 + 6)
1047 1048
		return;

1049
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0)
1050 1051
		return;

1052
	if (memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0)
1053 1054 1055 1056 1057 1058
		return;

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

1059 1060
	if (auth_alg != ifmgd->auth_alg ||
	    auth_transaction != ifmgd->auth_transaction)
1061 1062 1063 1064 1065 1066 1067 1068
		return;

	if (status_code != WLAN_STATUS_SUCCESS) {
		if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
			u8 algs[3];
			const int num_algs = ARRAY_SIZE(algs);
			int i, pos;
			algs[0] = algs[1] = algs[2] = 0xff;
1069
			if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_OPEN)
1070
				algs[0] = WLAN_AUTH_OPEN;
1071
			if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
1072
				algs[1] = WLAN_AUTH_SHARED_KEY;
1073
			if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
1074
				algs[2] = WLAN_AUTH_LEAP;
1075
			if (ifmgd->auth_alg == WLAN_AUTH_OPEN)
1076
				pos = 0;
1077
			else if (ifmgd->auth_alg == WLAN_AUTH_SHARED_KEY)
1078 1079 1080 1081 1082 1083 1084
				pos = 1;
			else
				pos = 2;
			for (i = 0; i < num_algs; i++) {
				pos++;
				if (pos >= num_algs)
					pos = 0;
1085
				if (algs[pos] == ifmgd->auth_alg ||
1086 1087 1088
				    algs[pos] == 0xff)
					continue;
				if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
1089
				    !ieee80211_sta_wep_configured(sdata))
1090
					continue;
1091
				ifmgd->auth_alg = algs[pos];
1092 1093 1094 1095 1096 1097
				break;
			}
		}
		return;
	}

1098
	switch (ifmgd->auth_alg) {
1099 1100
	case WLAN_AUTH_OPEN:
	case WLAN_AUTH_LEAP:
1101
	case WLAN_AUTH_FT:
1102
		ieee80211_auth_completed(sdata);
1103
		cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
1104 1105
		break;
	case WLAN_AUTH_SHARED_KEY:
1106
		if (ifmgd->auth_transaction == 4) {
1107
			ieee80211_auth_completed(sdata);
1108 1109
			cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
		} else
1110
			ieee80211_auth_challenge(sdata, mgmt, len);
1111 1112 1113 1114 1115
		break;
	}
}


1116
static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1117 1118 1119
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
1120
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1121 1122
	u16 reason_code;

1123
	if (len < 24 + 2)
1124 1125
		return;

1126
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN))
1127 1128 1129 1130
		return;

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

1131
	if (ifmgd->flags & IEEE80211_STA_AUTHENTICATED)
1132 1133
		printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
				sdata->dev->name, reason_code);
1134

1135 1136 1137 1138
	if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
	    (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
	     ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE ||
	     ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) {
1139 1140
		ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
		mod_timer(&ifmgd->timer, jiffies +
1141 1142 1143
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1144 1145
	ieee80211_set_disassoc(sdata, true, false, 0);
	ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
1146
	cfg80211_send_rx_deauth(sdata->dev, (u8 *) mgmt, len);
1147 1148 1149
}


1150
static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1151 1152 1153
				       struct ieee80211_mgmt *mgmt,
				       size_t len)
{
1154
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1155 1156
	u16 reason_code;

1157
	if (len < 24 + 2)
1158 1159
		return;

1160
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN))
1161 1162 1163 1164
		return;

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

1165
	if (ifmgd->flags & IEEE80211_STA_ASSOCIATED)
1166 1167
		printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
				sdata->dev->name, reason_code);
1168

1169 1170
	if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
	    ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
1171 1172
		ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
		mod_timer(&ifmgd->timer, jiffies +
1173 1174 1175
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1176
	ieee80211_set_disassoc(sdata, false, false, reason_code);
1177
	cfg80211_send_rx_disassoc(sdata->dev, (u8 *) mgmt, len);
1178 1179 1180
}


1181
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1182 1183 1184 1185
					 struct ieee80211_mgmt *mgmt,
					 size_t len,
					 int reassoc)
{
1186
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1187
	struct ieee80211_local *local = sdata->local;
1188
	struct ieee80211_supported_band *sband;
1189
	struct sta_info *sta;
1190
	u32 rates, basic_rates;
1191 1192
	u16 capab_info, status_code, aid;
	struct ieee802_11_elems elems;
J
Johannes Berg 已提交
1193
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1194
	u8 *pos;
J
Johannes Berg 已提交
1195
	u32 changed = 0;
1196
	int i, j;
1197
	bool have_higher_than_11mbit = false, newsta = false;
J
Johannes Berg 已提交
1198
	u16 ap_ht_cap_flags;
1199 1200 1201 1202

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

1203
	if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
1204 1205
		return;

1206
	if (len < 24 + 6)
1207 1208
		return;

1209
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0)
1210 1211 1212 1213 1214 1215
		return;

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

1216
	printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
1217
	       "status=%d aid=%d)\n",
1218
	       sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
1219
	       capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
1220

1221 1222 1223 1224
	pos = mgmt->u.assoc_resp.variable;
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);

	if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
1225 1226
	    elems.timeout_int && elems.timeout_int_len == 5 &&
	    elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
1227
		u32 tu, ms;
1228
		tu = get_unaligned_le32(elems.timeout_int + 1);
1229 1230 1231 1232 1233
		ms = tu * 1024 / 1000;
		printk(KERN_DEBUG "%s: AP rejected association temporarily; "
		       "comeback duration %u TU (%u ms)\n",
		       sdata->dev->name, tu, ms);
		if (ms > IEEE80211_ASSOC_TIMEOUT)
1234
			mod_timer(&ifmgd->timer,
1235 1236 1237 1238
				  jiffies + msecs_to_jiffies(ms));
		return;
	}

1239 1240
	if (status_code != WLAN_STATUS_SUCCESS) {
		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
1241
		       sdata->dev->name, status_code);
1242 1243 1244
		/* if this was a reassociation, ensure we try a "full"
		 * association next time. This works around some broken APs
		 * which do not correctly reject reassociation requests. */
1245
		ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1246 1247 1248
		return;
	}

1249 1250
	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
		printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
1251
		       "set\n", sdata->dev->name, aid);
1252 1253
	aid &= ~(BIT(15) | BIT(14));

1254 1255
	if (!elems.supp_rates) {
		printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
1256
		       sdata->dev->name);
1257 1258 1259
		return;
	}

1260
	printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
1261 1262
	ifmgd->aid = aid;
	ifmgd->ap_capab = capab_info;
1263

1264 1265 1266 1267 1268
	kfree(ifmgd->assocresp_ies);
	ifmgd->assocresp_ies_len = len - (pos - (u8 *) mgmt);
	ifmgd->assocresp_ies = kmalloc(ifmgd->assocresp_ies_len, GFP_KERNEL);
	if (ifmgd->assocresp_ies)
		memcpy(ifmgd->assocresp_ies, pos, ifmgd->assocresp_ies_len);
1269

1270 1271
	rcu_read_lock();

1272
	/* Add STA entry for the AP */
1273
	sta = sta_info_get(local, ifmgd->bssid);
1274
	if (!sta) {
1275
		newsta = true;
1276

1277
		sta = sta_info_alloc(sdata, ifmgd->bssid, GFP_ATOMIC);
J
Johannes Berg 已提交
1278 1279
		if (!sta) {
			printk(KERN_DEBUG "%s: failed to alloc STA entry for"
1280
			       " the AP\n", sdata->dev->name);
1281
			rcu_read_unlock();
1282 1283
			return;
		}
1284

J
Johannes Berg 已提交
1285 1286
		/* update new sta with its last rx activity */
		sta->last_rx = jiffies;
1287 1288
	}

J
Johannes Berg 已提交
1289 1290 1291 1292 1293 1294 1295 1296 1297
	/*
	 * FIXME: Do we really need to update the sta_info's information here?
	 *	  We already know about the AP (we found it in our list) so it
	 *	  should already be filled with the right info, no?
	 *	  As is stands, all this is racy because typically we assume
	 *	  the information that is filled in here (except flags) doesn't
	 *	  change while a STA structure is alive. As such, it should move
	 *	  to between the sta_info_alloc() and sta_info_insert() above.
	 */
1298

J
Johannes Berg 已提交
1299 1300
	set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
			   WLAN_STA_AUTHORIZED);
1301

J
Johannes Berg 已提交
1302 1303 1304
	rates = 0;
	basic_rates = 0;
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1305

J
Johannes Berg 已提交
1306 1307
	for (i = 0; i < elems.supp_rates_len; i++) {
		int rate = (elems.supp_rates[i] & 0x7f) * 5;
1308
		bool is_basic = !!(elems.supp_rates[i] & 0x80);
1309

J
Johannes Berg 已提交
1310 1311 1312 1313
		if (rate > 110)
			have_higher_than_11mbit = true;

		for (j = 0; j < sband->n_bitrates; j++) {
1314
			if (sband->bitrates[j].bitrate == rate) {
J
Johannes Berg 已提交
1315
				rates |= BIT(j);
1316 1317 1318 1319
				if (is_basic)
					basic_rates |= BIT(j);
				break;
			}
1320 1321 1322
		}
	}

J
Johannes Berg 已提交
1323 1324
	for (i = 0; i < elems.ext_supp_rates_len; i++) {
		int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
1325
		bool is_basic = !!(elems.supp_rates[i] & 0x80);
1326

J
Johannes Berg 已提交
1327 1328
		if (rate > 110)
			have_higher_than_11mbit = true;
1329

J
Johannes Berg 已提交
1330
		for (j = 0; j < sband->n_bitrates; j++) {
1331
			if (sband->bitrates[j].bitrate == rate) {
J
Johannes Berg 已提交
1332
				rates |= BIT(j);
1333 1334 1335 1336
				if (is_basic)
					basic_rates |= BIT(j);
				break;
			}
J
Johannes Berg 已提交
1337
		}
1338
	}
1339

J
Johannes Berg 已提交
1340
	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
J
Johannes Berg 已提交
1341
	sdata->vif.bss_conf.basic_rates = basic_rates;
J
Johannes Berg 已提交
1342 1343 1344 1345 1346 1347 1348

	/* cf. IEEE 802.11 9.2.12 */
	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
	    have_higher_than_11mbit)
		sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
	else
		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
1349

1350 1351
	/* If TKIP/WEP is used, no need to parse AP's HT capabilities */
	if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
J
Johannes Berg 已提交
1352
		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
J
Johannes Berg 已提交
1353
				elems.ht_cap_elem, &sta->sta.ht_cap);
J
Johannes Berg 已提交
1354 1355

	ap_ht_cap_flags = sta->sta.ht_cap.cap;
1356

1357
	rate_control_rate_init(sta);
1358

1359
	if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
1360 1361
		set_sta_flags(sta, WLAN_STA_MFP);

1362
	if (elems.wmm_param)
J
Johannes Berg 已提交
1363
		set_sta_flags(sta, WLAN_STA_WME);
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377

	if (newsta) {
		int err = sta_info_insert(sta);
		if (err) {
			printk(KERN_DEBUG "%s: failed to insert STA entry for"
			       " the AP (error %d)\n", sdata->dev->name, err);
			rcu_read_unlock();
			return;
		}
	}

	rcu_read_unlock();

	if (elems.wmm_param)
1378
		ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
J
Johannes Berg 已提交
1379
					 elems.wmm_param_len);
1380

J
Johannes Berg 已提交
1381
	if (elems.ht_info_elem && elems.wmm_param &&
1382 1383
	    (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
	    !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
J
Johannes Berg 已提交
1384 1385 1386
		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
					       ap_ht_cap_flags);

J
Johannes Berg 已提交
1387 1388 1389 1390
	/* set AID and assoc capability,
	 * ieee80211_set_associated() will tell the driver */
	bss_conf->aid = aid;
	bss_conf->assoc_capability = capab_info;
1391
	ieee80211_set_associated(sdata, changed);
1392

1393
	ieee80211_associated(sdata);
1394
	cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
1395 1396 1397
}


1398 1399 1400 1401 1402 1403 1404 1405 1406
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
				  struct ieee80211_mgmt *mgmt,
				  size_t len,
				  struct ieee80211_rx_status *rx_status,
				  struct ieee802_11_elems *elems,
				  bool beacon)
{
	struct ieee80211_local *local = sdata->local;
	int freq;
1407
	struct ieee80211_bss *bss;
1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420
	struct ieee80211_channel *channel;

	if (elems->ds_params && elems->ds_params_len == 1)
		freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
	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,
1421
					channel, beacon);
1422 1423 1424
	if (!bss)
		return;

S
Sujith 已提交
1425
	if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
1426
	    (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) {
S
Sujith 已提交
1427 1428 1429 1430 1431
		struct ieee80211_channel_sw_ie *sw_elem =
			(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
		ieee80211_process_chanswitch(sdata, sw_elem, bss);
	}

1432
	ieee80211_rx_bss_put(local, bss);
1433 1434 1435
}


1436
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1437 1438 1439 1440
					 struct ieee80211_mgmt *mgmt,
					 size_t len,
					 struct ieee80211_rx_status *rx_status)
{
1441 1442 1443
	size_t baselen;
	struct ieee802_11_elems elems;

1444 1445 1446
	if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
		return; /* ignore ProbeResp to foreign address */

1447 1448 1449 1450 1451 1452 1453
	baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
	if (baselen > len)
		return;

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

1454
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1455 1456 1457

	/* direct probe may be part of the association flow */
	if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
1458
	    &sdata->u.mgd.request)) {
1459 1460
		printk(KERN_DEBUG "%s direct probe responded\n",
		       sdata->dev->name);
1461
		ieee80211_authenticate(sdata);
1462
	}
1463 1464
}

1465
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1466 1467 1468 1469
				     struct ieee80211_mgmt *mgmt,
				     size_t len,
				     struct ieee80211_rx_status *rx_status)
{
1470
	struct ieee80211_if_managed *ifmgd;
1471 1472
	size_t baselen;
	struct ieee802_11_elems elems;
1473
	struct ieee80211_local *local = sdata->local;
1474
	u32 changed = 0;
1475
	bool erp_valid, directed_tim;
J
Johannes Berg 已提交
1476
	u8 erp_value = 0;
1477

1478 1479 1480 1481 1482 1483 1484
	/* Process beacon from the current BSS */
	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
	if (baselen > len)
		return;

	ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);

1485
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
1486

1487
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1488 1489
		return;

1490 1491 1492 1493
	ifmgd = &sdata->u.mgd;

	if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED) ||
	    memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0)
1494 1495
		return;

S
Sujith 已提交
1496 1497 1498
	if (rx_status->freq != local->hw.conf.channel->center_freq)
		return;

1499
	ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
1500 1501
				 elems.wmm_param_len);

1502
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
1503
		directed_tim = ieee80211_check_tim(&elems, ifmgd->aid);
1504

1505
		if (directed_tim) {
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
			if (local->hw.conf.dynamic_ps_timeout > 0) {
				local->hw.conf.flags &= ~IEEE80211_CONF_PS;
				ieee80211_hw_config(local,
						    IEEE80211_CONF_CHANGE_PS);
				ieee80211_send_nullfunc(local, sdata, 0);
			} else {
				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);
			}
1524 1525
		}
	}
J
Johannes Berg 已提交
1526 1527 1528 1529 1530 1531

	if (elems.erp_info && elems.erp_info_len >= 1) {
		erp_valid = true;
		erp_value = elems.erp_info[0];
	} else {
		erp_valid = false;
1532
	}
J
Johannes Berg 已提交
1533 1534 1535
	changed |= ieee80211_handle_bss_capability(sdata,
			le16_to_cpu(mgmt->u.beacon.capab_info),
			erp_valid, erp_value);
1536

1537

1538
	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
1539
	    !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED)) {
J
Johannes Berg 已提交
1540 1541 1542 1543 1544 1545
		struct sta_info *sta;
		struct ieee80211_supported_band *sband;
		u16 ap_ht_cap_flags;

		rcu_read_lock();

1546
		sta = sta_info_get(local, ifmgd->bssid);
J
Johannes Berg 已提交
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562
		if (!sta) {
			rcu_read_unlock();
			return;
		}

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

		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
				elems.ht_cap_elem, &sta->sta.ht_cap);

		ap_ht_cap_flags = sta->sta.ht_cap.cap;

		rcu_read_unlock();

		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
					       ap_ht_cap_flags);
1563 1564
	}

1565 1566 1567 1568 1569
	if (elems.country_elem) {
		/* Note we are only reviewing this on beacons
		 * for the BSSID we are associated to */
		regulatory_hint_11d(local->hw.wiphy,
			elems.country_elem, elems.country_elem_len);
1570 1571 1572 1573 1574 1575 1576

		/* TODO: IBSS also needs this */
		if (elems.pwr_constr_elem)
			ieee80211_handle_pwr_constr(sdata,
				le16_to_cpu(mgmt->u.probe_resp.capab_info),
				elems.pwr_constr_elem,
				elems.pwr_constr_elem_len);
1577 1578
	}

1579
	ieee80211_bss_info_change_notify(sdata, changed);
1580 1581
}

1582 1583 1584
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
					  struct sk_buff *skb,
					  struct ieee80211_rx_status *rx_status)
1585
{
1586
	struct ieee80211_local *local = sdata->local;
1587 1588 1589 1590
	struct ieee80211_mgmt *mgmt;
	u16 fc;

	if (skb->len < 24)
1591
		return RX_DROP_MONITOR;
1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605

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

	switch (fc & IEEE80211_FCTL_STYPE) {
	case IEEE80211_STYPE_PROBE_REQ:
	case IEEE80211_STYPE_PROBE_RESP:
	case IEEE80211_STYPE_BEACON:
		memcpy(skb->cb, rx_status, sizeof(*rx_status));
	case IEEE80211_STYPE_AUTH:
	case IEEE80211_STYPE_ASSOC_RESP:
	case IEEE80211_STYPE_REASSOC_RESP:
	case IEEE80211_STYPE_DEAUTH:
	case IEEE80211_STYPE_DISASSOC:
1606 1607 1608
		skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
		queue_work(local->hw.workqueue, &sdata->u.mgd.work);
		return RX_QUEUED;
1609 1610
	}

1611
	return RX_DROP_MONITOR;
1612 1613
}

1614
static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1615 1616 1617 1618 1619 1620 1621 1622 1623 1624
					 struct sk_buff *skb)
{
	struct ieee80211_rx_status *rx_status;
	struct ieee80211_mgmt *mgmt;
	u16 fc;

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

1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
	switch (fc & IEEE80211_FCTL_STYPE) {
	case IEEE80211_STYPE_PROBE_RESP:
		ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
					     rx_status);
		break;
	case IEEE80211_STYPE_BEACON:
		ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
					 rx_status);
		break;
	case IEEE80211_STYPE_AUTH:
		ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
		break;
	case IEEE80211_STYPE_ASSOC_RESP:
		ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, 0);
		break;
	case IEEE80211_STYPE_REASSOC_RESP:
		ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, 1);
		break;
	case IEEE80211_STYPE_DEAUTH:
		ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
		break;
	case IEEE80211_STYPE_DISASSOC:
		ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
		break;
1649 1650 1651 1652 1653
	}

	kfree_skb(skb);
}

J
Johannes Berg 已提交
1654
static void ieee80211_sta_timer(unsigned long data)
1655
{
J
Johannes Berg 已提交
1656 1657
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
1658
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1659
	struct ieee80211_local *local = sdata->local;
1660

1661 1662
	set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
	queue_work(local->hw.workqueue, &ifmgd->work);
1663 1664
}

1665
static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata)
1666
{
1667
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1668
	struct ieee80211_local *local = sdata->local;
1669 1670 1671 1672 1673 1674

	if (local->ops->reset_tsf) {
		/* Reset own TSF to allow time synchronization work. */
		local->ops->reset_tsf(local_to_hw(local));
	}

1675
	ifmgd->wmm_last_param_set = -1; /* allow any WMM update */
1676 1677


1678 1679 1680 1681 1682 1683
	if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_OPEN)
		ifmgd->auth_alg = WLAN_AUTH_OPEN;
	else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
		ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY;
	else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
		ifmgd->auth_alg = WLAN_AUTH_LEAP;
1684 1685
	else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_FT)
		ifmgd->auth_alg = WLAN_AUTH_FT;
1686
	else
1687 1688 1689 1690 1691 1692 1693
		ifmgd->auth_alg = WLAN_AUTH_OPEN;
	ifmgd->auth_transaction = -1;
	ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
	ifmgd->assoc_scan_tries = 0;
	ifmgd->direct_probe_tries = 0;
	ifmgd->auth_tries = 0;
	ifmgd->assoc_tries = 0;
1694
	netif_tx_stop_all_queues(sdata->dev);
1695
	netif_carrier_off(sdata->dev);
1696 1697
}

1698
static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
1699
{
1700
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1701
	struct ieee80211_local *local = sdata->local;
1702
	struct ieee80211_bss *bss;
1703 1704
	u8 *bssid = ifmgd->bssid, *ssid = ifmgd->ssid;
	u8 ssid_len = ifmgd->ssid_len;
1705 1706 1707 1708
	u16 capa_mask = WLAN_CAPABILITY_ESS;
	u16 capa_val = WLAN_CAPABILITY_ESS;
	struct ieee80211_channel *chan = local->oper_channel;

1709 1710
	if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
	    ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL |
1711 1712 1713 1714 1715
			    IEEE80211_STA_AUTO_BSSID_SEL |
			    IEEE80211_STA_AUTO_CHANNEL_SEL)) {
		capa_mask |= WLAN_CAPABILITY_PRIVACY;
		if (sdata->default_key)
			capa_val |= WLAN_CAPABILITY_PRIVACY;
1716
	}
1717

1718
	if (ifmgd->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
1719 1720
		chan = NULL;

1721
	if (ifmgd->flags & IEEE80211_STA_AUTO_BSSID_SEL)
1722 1723
		bssid = NULL;

1724
	if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL) {
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
		ssid = NULL;
		ssid_len = 0;
	}

	bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan,
				       bssid, ssid, ssid_len,
				       capa_mask, capa_val);

	if (bss) {
		ieee80211_set_freq(sdata, bss->cbss.channel->center_freq);
1735
		if (!(ifmgd->flags & IEEE80211_STA_SSID_SET))
1736 1737 1738 1739 1740
			ieee80211_sta_set_ssid(sdata, bss->ssid,
					       bss->ssid_len);
		ieee80211_sta_set_bssid(sdata, bss->cbss.bssid);
		ieee80211_sta_def_wmm_params(sdata, bss->supp_rates_len,
						    bss->supp_rates);
1741 1742
		if (sdata->u.mgd.mfp == IEEE80211_MFP_REQUIRED)
			sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
1743
		else
1744
			sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
1745

J
Johannes Berg 已提交
1746 1747 1748
		/* Send out direct probe if no probe resp was received or
		 * the one we have is outdated
		 */
1749 1750
		if (!bss->last_probe_resp ||
		    time_after(jiffies, bss->last_probe_resp
J
Johannes Berg 已提交
1751
					+ IEEE80211_SCAN_RESULT_EXPIRE))
1752
			ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
J
Johannes Berg 已提交
1753
		else
1754
			ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
1755

1756
		ieee80211_rx_bss_put(local, bss);
1757
		ieee80211_sta_reset_auth(sdata);
J
Johannes Berg 已提交
1758 1759
		return 0;
	} else {
1760 1761
		if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) {
			ifmgd->assoc_scan_tries++;
1762 1763 1764 1765
			/* XXX maybe racy? */
			if (local->scan_req)
				return -1;
			memcpy(local->int_scan_req.ssids[0].ssid,
1766 1767
			       ifmgd->ssid, IEEE80211_MAX_SSID_LEN);
			if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL)
1768
				local->int_scan_req.ssids[0].ssid_len = 0;
J
Johannes Berg 已提交
1769
			else
1770
				local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len;
1771 1772 1773 1774

			if (ieee80211_start_scan(sdata, &local->int_scan_req))
				ieee80211_scan_failed(local);

1775 1776
			ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
			set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
1777
		} else {
1778 1779
			ifmgd->assoc_scan_tries = 0;
			ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1780
		}
J
Johannes Berg 已提交
1781 1782 1783 1784 1785 1786 1787 1788
	}
	return -1;
}


static void ieee80211_sta_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
1789
		container_of(work, struct ieee80211_sub_if_data, u.mgd.work);
J
Johannes Berg 已提交
1790
	struct ieee80211_local *local = sdata->local;
1791
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1792 1793 1794 1795 1796
	struct sk_buff *skb;

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

1797
	if (local->sw_scanning || local->hw_scanning)
J
Johannes Berg 已提交
1798 1799
		return;

1800
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
J
Johannes Berg 已提交
1801
		return;
1802
	ifmgd = &sdata->u.mgd;
1803

1804
	while ((skb = skb_dequeue(&ifmgd->skb_queue)))
J
Johannes Berg 已提交
1805 1806
		ieee80211_sta_rx_queued_mgmt(sdata, skb);

1807 1808 1809 1810
	if (ifmgd->state != IEEE80211_STA_MLME_DIRECT_PROBE &&
	    ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE &&
	    ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE &&
	    test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) {
1811 1812 1813 1814 1815 1816 1817 1818
		/*
		 * The call to ieee80211_start_scan can fail but ieee80211_request_scan
		 * (which queued ieee80211_sta_work) did not return an error. Thus, call
		 * ieee80211_scan_failed here if ieee80211_start_scan fails in order to
		 * notify the scan requester.
		 */
		if (ieee80211_start_scan(sdata, local->scan_req))
			ieee80211_scan_failed(local);
J
Johannes Berg 已提交
1819
		return;
1820 1821
	}

1822 1823
	if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request)) {
		if (ieee80211_sta_config_auth(sdata))
J
Johannes Berg 已提交
1824
			return;
1825 1826
		clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
	} else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request))
J
Johannes Berg 已提交
1827
		return;
1828

1829
	switch (ifmgd->state) {
J
Johannes Berg 已提交
1830 1831 1832
	case IEEE80211_STA_MLME_DISABLED:
		break;
	case IEEE80211_STA_MLME_DIRECT_PROBE:
1833
		ieee80211_direct_probe(sdata);
J
Johannes Berg 已提交
1834 1835
		break;
	case IEEE80211_STA_MLME_AUTHENTICATE:
1836
		ieee80211_authenticate(sdata);
J
Johannes Berg 已提交
1837 1838
		break;
	case IEEE80211_STA_MLME_ASSOCIATE:
1839
		ieee80211_associate(sdata);
J
Johannes Berg 已提交
1840 1841
		break;
	case IEEE80211_STA_MLME_ASSOCIATED:
1842
		ieee80211_associated(sdata);
J
Johannes Berg 已提交
1843 1844 1845 1846 1847 1848
		break;
	default:
		WARN_ON(1);
		break;
	}

1849
	if (ieee80211_privacy_mismatch(sdata)) {
J
Johannes Berg 已提交
1850 1851 1852
		printk(KERN_DEBUG "%s: privacy configuration mismatch and "
		       "mixed-cell disabled - disassociate\n", sdata->dev->name);

1853
		ieee80211_set_disassoc(sdata, false, true,
J
Johannes Berg 已提交
1854 1855
					WLAN_REASON_UNSPECIFIED);
	}
1856 1857
}

J
Johannes Berg 已提交
1858 1859
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
1860
	if (sdata->vif.type == NL80211_IFTYPE_STATION)
J
Johannes Berg 已提交
1861
		queue_work(sdata->local->hw.workqueue,
1862
			   &sdata->u.mgd.work);
J
Johannes Berg 已提交
1863
}
1864

J
Johannes Berg 已提交
1865 1866
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1867
{
1868
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1869

1870 1871 1872 1873
	ifmgd = &sdata->u.mgd;
	INIT_WORK(&ifmgd->work, ieee80211_sta_work);
	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
	setup_timer(&ifmgd->timer, ieee80211_sta_timer,
S
Sujith 已提交
1874
		    (unsigned long) sdata);
1875
	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
J
Johannes Berg 已提交
1876
		    (unsigned long) sdata);
1877
	skb_queue_head_init(&ifmgd->skb_queue);
J
Johannes Berg 已提交
1878

1879 1880
	ifmgd->capab = WLAN_CAPABILITY_ESS;
	ifmgd->auth_algs = IEEE80211_AUTH_ALG_OPEN |
J
Johannes Berg 已提交
1881
		IEEE80211_AUTH_ALG_SHARED_KEY;
1882
	ifmgd->flags |= IEEE80211_STA_CREATE_IBSS |
J
Johannes Berg 已提交
1883 1884
		IEEE80211_STA_AUTO_BSSID_SEL |
		IEEE80211_STA_AUTO_CHANNEL_SEL;
1885
	if (sdata->local->hw.queues >= 4)
1886
		ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
1887 1888
}

J
Johannes Berg 已提交
1889
/* configuration hooks */
1890
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
1891
{
1892
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1893 1894
	struct ieee80211_local *local = sdata->local;

1895
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
J
Johannes Berg 已提交
1896
		return;
J
Johannes Berg 已提交
1897

1898
	if ((ifmgd->flags & (IEEE80211_STA_BSSID_SET |
J
Johannes Berg 已提交
1899
			     IEEE80211_STA_AUTO_BSSID_SEL)) &&
1900
	    (ifmgd->flags & (IEEE80211_STA_SSID_SET |
J
Johannes Berg 已提交
1901
			     IEEE80211_STA_AUTO_SSID_SEL))) {
J
Johannes Berg 已提交
1902

1903 1904
		if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
			ieee80211_set_disassoc(sdata, true, true,
J
Johannes Berg 已提交
1905
					       WLAN_REASON_DEAUTH_LEAVING);
J
Johannes Berg 已提交
1906

1907 1908 1909 1910 1911
		if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) ||
		    ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
			set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
		else if (ifmgd->flags & IEEE80211_STA_EXT_SME)
			set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
1912
		queue_work(local->hw.workqueue, &ifmgd->work);
J
Johannes Berg 已提交
1913 1914
	}
}
J
Johannes Berg 已提交
1915

1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927
int ieee80211_sta_commit(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

	if (ifmgd->ssid_len)
		ifmgd->flags |= IEEE80211_STA_SSID_SET;
	else
		ifmgd->flags &= ~IEEE80211_STA_SSID_SET;

	return 0;
}

J
Johannes Berg 已提交
1928 1929
int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
{
1930
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1931

J
Johannes Berg 已提交
1932 1933 1934
	if (len > IEEE80211_MAX_SSID_LEN)
		return -EINVAL;

1935
	ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1936

1937
	if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) {
1938 1939 1940 1941
		/*
		 * Do not use reassociation if SSID is changed (different ESS).
		 */
		ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1942 1943 1944
		memset(ifmgd->ssid, 0, sizeof(ifmgd->ssid));
		memcpy(ifmgd->ssid, ssid, len);
		ifmgd->ssid_len = len;
J
Johannes Berg 已提交
1945 1946
	}

1947
	return ieee80211_sta_commit(sdata);
J
Johannes Berg 已提交
1948 1949 1950 1951
}

int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
{
1952 1953 1954
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	memcpy(ssid, ifmgd->ssid, ifmgd->ssid_len);
	*len = ifmgd->ssid_len;
J
Johannes Berg 已提交
1955 1956 1957 1958 1959
	return 0;
}

int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
{
1960
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1961

1962
	if (is_valid_ether_addr(bssid)) {
1963 1964
		memcpy(ifmgd->bssid, bssid, ETH_ALEN);
		ifmgd->flags |= IEEE80211_STA_BSSID_SET;
1965
	} else {
1966 1967
		memset(ifmgd->bssid, 0, ETH_ALEN);
		ifmgd->flags &= ~IEEE80211_STA_BSSID_SET;
1968 1969 1970 1971
	}

	if (netif_running(sdata->dev)) {
		if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) {
J
Johannes Berg 已提交
1972 1973 1974 1975
			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
			       "the low-level driver\n", sdata->dev->name);
		}
	}
J
Johannes Berg 已提交
1976

1977
	return ieee80211_sta_commit(sdata);
J
Johannes Berg 已提交
1978 1979
}

1980 1981
int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
			       const char *ie, size_t len)
J
Johannes Berg 已提交
1982
{
1983
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1984

1985
	kfree(ifmgd->extra_ie);
J
Johannes Berg 已提交
1986
	if (len == 0) {
1987 1988
		ifmgd->extra_ie = NULL;
		ifmgd->extra_ie_len = 0;
J
Johannes Berg 已提交
1989 1990
		return 0;
	}
1991 1992 1993
	ifmgd->extra_ie = kmalloc(len, GFP_KERNEL);
	if (!ifmgd->extra_ie) {
		ifmgd->extra_ie_len = 0;
J
Johannes Berg 已提交
1994 1995
		return -ENOMEM;
	}
1996 1997
	memcpy(ifmgd->extra_ie, ie, len);
	ifmgd->extra_ie_len = len;
J
Johannes Berg 已提交
1998
	return 0;
J
Johannes Berg 已提交
1999 2000
}

2001
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
2002
{
2003
	printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
2004
	       sdata->dev->name, reason);
2005

2006
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
2007 2008
		return -EINVAL;

2009
	ieee80211_set_disassoc(sdata, true, true, reason);
2010 2011 2012
	return 0;
}

2013
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
2014
{
2015
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2016

2017
	printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
2018
	       sdata->dev->name, reason);
2019

2020
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
2021 2022
		return -EINVAL;

2023 2024
	if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED))
		return -ENOLINK;
2025

2026
	ieee80211_set_disassoc(sdata, false, true, reason);
2027 2028
	return 0;
}
2029

J
Johannes Berg 已提交
2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040
/* scan finished notification */
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
{
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;

	/* Restart STA timers */
	rcu_read_lock();
	list_for_each_entry_rcu(sdata, &local->interfaces, list)
		ieee80211_restart_sta_timer(sdata);
	rcu_read_unlock();
}
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061

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);
2062
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
2063 2064 2065 2066

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

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

2070
	local->hw.conf.flags |= IEEE80211_CONF_PS;
2071 2072 2073 2074 2075 2076 2077 2078 2079
	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);
}
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112

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