mlme.c 57.2 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 735

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

		/*
		 * 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);
751 752 753
		return;
	}

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

758 759 760
	ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, NULL, 0,
			    ifmgd->bssid, 0);
	ifmgd->auth_transaction = 2;
761

762
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
763 764
}

765 766 767 768
/*
 * The disassoc 'reason' argument can be either our own reason
 * if self disconnected or a reason code from the AP.
 */
769
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
770 771
				   bool deauth, bool self_disconnected,
				   u16 reason)
772
{
773
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
774 775
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
776
	u32 changed = 0, config_changed = 0;
777 778 779

	rcu_read_lock();

780
	sta = sta_info_get(local, ifmgd->bssid);
781 782 783 784 785 786
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	if (deauth) {
787 788
		ifmgd->direct_probe_tries = 0;
		ifmgd->auth_tries = 0;
789
	}
790 791
	ifmgd->assoc_scan_tries = 0;
	ifmgd->assoc_tries = 0;
792

793
	netif_tx_stop_all_queues(sdata->dev);
794 795
	netif_carrier_off(sdata->dev);

796
	ieee80211_sta_tear_down_BA_sessions(sta);
797 798 799

	if (self_disconnected) {
		if (deauth)
800 801
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DEAUTH, reason);
802
		else
803 804
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DISASSOC, reason);
805 806
	}

807
	ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
808 809 810
	changed |= ieee80211_reset_erp_info(sdata);

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

814
	ieee80211_sta_send_apinfo(sdata);
815

816
	if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
817 818
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
819
				sdata->local->hw.conf.channel->center_freq,
820
				ifmgd->ssid, ifmgd->ssid_len);
821
	}
822 823 824

	rcu_read_unlock();

825
	/* channel(_type) changes are handled by ieee80211_hw_config */
S
Sujith 已提交
826
	local->oper_channel_type = NL80211_CHAN_NO_HT;
827

828 829
	local->power_constr_level = 0;

830 831 832
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

833 834 835 836
	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		config_changed |= IEEE80211_CONF_CHANGE_PS;
	}
J
Johannes Berg 已提交
837

838
	ieee80211_hw_config(local, config_changed);
J
Johannes Berg 已提交
839
	ieee80211_bss_info_change_notify(sdata, changed);
840 841 842

	rcu_read_lock();

843
	sta = sta_info_get(local, ifmgd->bssid);
844 845 846 847 848 849 850 851 852 853
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	sta_info_unlink(&sta);

	rcu_read_unlock();

	sta_info_destroy(sta);
854
}
855

856 857 858 859 860 861 862 863
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;
}

864
static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata)
865
{
866
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
867
	struct ieee80211_local *local = sdata->local;
868
	struct ieee80211_bss *bss;
869 870 871
	int bss_privacy;
	int wep_privacy;
	int privacy_invoked;
872

873
	if (!ifmgd || (ifmgd->flags & IEEE80211_STA_MIXED_CELL))
874 875
		return 0;

876
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
877
				   local->hw.conf.channel->center_freq,
878
				   ifmgd->ssid, ifmgd->ssid_len);
879 880 881
	if (!bss)
		return 0;

882
	bss_privacy = !!(bss->cbss.capability & WLAN_CAPABILITY_PRIVACY);
883
	wep_privacy = !!ieee80211_sta_wep_configured(sdata);
884
	privacy_invoked = !!(ifmgd->flags & IEEE80211_STA_PRIVACY_INVOKED);
885

886
	ieee80211_rx_bss_put(local, bss);
887

888 889 890 891
	if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
		return 0;

	return 1;
892 893
}

894
static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
895
{
896
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
897
	struct ieee80211_local *local = sdata->local;
898 899 900

	ifmgd->assoc_tries++;
	if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
901
		printk(KERN_DEBUG "%s: association with AP %pM"
902
		       " timed out\n",
903 904 905 906
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_sta_send_apinfo(sdata);
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
907
				sdata->local->hw.conf.channel->center_freq,
908
				ifmgd->ssid, ifmgd->ssid_len);
909 910 911 912 913 914
		/*
		 * 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);
915 916 917
		return;
	}

918
	ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
919
	printk(KERN_DEBUG "%s: associate with AP %pM\n",
920 921
	       sdata->dev->name, ifmgd->bssid);
	if (ieee80211_privacy_mismatch(sdata)) {
922
		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
923
		       "mixed-cell disabled - abort association\n", sdata->dev->name);
924
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
925 926 927
		return;
	}

928
	ieee80211_send_assoc(sdata);
929

930
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
931 932 933
}


934
static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
935
{
936
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
937
	struct ieee80211_local *local = sdata->local;
938 939 940 941 942 943 944 945
	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 */

946
	ifmgd->state = IEEE80211_STA_MLME_ASSOCIATED;
947

948 949
	rcu_read_lock();

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

	rcu_read_unlock();

986
	if (disassoc)
987
		ieee80211_set_disassoc(sdata, true, true,
J
Johannes Berg 已提交
988
					WLAN_REASON_PREV_AUTH_NOT_VALID);
989
	else
990
		mod_timer(&ifmgd->timer, jiffies +
J
Johannes Berg 已提交
991
				      IEEE80211_MONITORING_INTERVAL);
992 993 994
}


995
static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata)
996
{
997 998
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

999
	printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
1000 1001
	ifmgd->flags |= IEEE80211_STA_AUTHENTICATED;
	ieee80211_associate(sdata);
1002 1003 1004
}


1005
static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1006 1007 1008 1009 1010 1011 1012
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u8 *pos;
	struct ieee802_11_elems elems;

	pos = mgmt->u.auth.variable;
1013
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1014
	if (!elems.challenge)
1015
		return;
1016 1017 1018 1019
	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;
1020 1021
}

1022
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1023 1024 1025
				   struct ieee80211_mgmt *mgmt,
				   size_t len)
{
1026
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1027 1028
	u16 auth_alg, auth_transaction, status_code;

1029
	if (ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE)
1030 1031
		return;

1032
	if (len < 24 + 6)
1033 1034
		return;

1035
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0)
1036 1037
		return;

1038
	if (memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0)
1039 1040 1041 1042 1043 1044
		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);

1045 1046
	if (auth_alg != ifmgd->auth_alg ||
	    auth_transaction != ifmgd->auth_transaction)
1047 1048 1049 1050 1051 1052 1053 1054
		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;
1055
			if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_OPEN)
1056
				algs[0] = WLAN_AUTH_OPEN;
1057
			if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
1058
				algs[1] = WLAN_AUTH_SHARED_KEY;
1059
			if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
1060
				algs[2] = WLAN_AUTH_LEAP;
1061
			if (ifmgd->auth_alg == WLAN_AUTH_OPEN)
1062
				pos = 0;
1063
			else if (ifmgd->auth_alg == WLAN_AUTH_SHARED_KEY)
1064 1065 1066 1067 1068 1069 1070
				pos = 1;
			else
				pos = 2;
			for (i = 0; i < num_algs; i++) {
				pos++;
				if (pos >= num_algs)
					pos = 0;
1071
				if (algs[pos] == ifmgd->auth_alg ||
1072 1073 1074
				    algs[pos] == 0xff)
					continue;
				if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
1075
				    !ieee80211_sta_wep_configured(sdata))
1076
					continue;
1077
				ifmgd->auth_alg = algs[pos];
1078 1079 1080 1081 1082 1083
				break;
			}
		}
		return;
	}

1084
	switch (ifmgd->auth_alg) {
1085 1086
	case WLAN_AUTH_OPEN:
	case WLAN_AUTH_LEAP:
1087
		ieee80211_auth_completed(sdata);
1088
		cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
1089 1090
		break;
	case WLAN_AUTH_SHARED_KEY:
1091
		if (ifmgd->auth_transaction == 4) {
1092
			ieee80211_auth_completed(sdata);
1093 1094
			cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
		} else
1095
			ieee80211_auth_challenge(sdata, mgmt, len);
1096 1097 1098 1099 1100
		break;
	}
}


1101
static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1102 1103 1104
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
1105
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1106 1107
	u16 reason_code;

1108
	if (len < 24 + 2)
1109 1110
		return;

1111
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN))
1112 1113 1114 1115
		return;

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

1116
	if (ifmgd->flags & IEEE80211_STA_AUTHENTICATED)
1117 1118
		printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
				sdata->dev->name, reason_code);
1119

1120 1121 1122 1123 1124
	if (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
	    ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE ||
	    ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
		ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
		mod_timer(&ifmgd->timer, jiffies +
1125 1126 1127
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1128 1129
	ieee80211_set_disassoc(sdata, true, false, 0);
	ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
1130
	cfg80211_send_rx_deauth(sdata->dev, (u8 *) mgmt, len);
1131 1132 1133
}


1134
static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1135 1136 1137
				       struct ieee80211_mgmt *mgmt,
				       size_t len)
{
1138
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1139 1140
	u16 reason_code;

1141
	if (len < 24 + 2)
1142 1143
		return;

1144
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN))
1145 1146 1147 1148
		return;

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

1149
	if (ifmgd->flags & IEEE80211_STA_ASSOCIATED)
1150 1151
		printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
				sdata->dev->name, reason_code);
1152

1153 1154 1155
	if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
		ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
		mod_timer(&ifmgd->timer, jiffies +
1156 1157 1158
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1159
	ieee80211_set_disassoc(sdata, false, false, reason_code);
1160
	cfg80211_send_rx_disassoc(sdata->dev, (u8 *) mgmt, len);
1161 1162 1163
}


1164
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1165 1166 1167 1168
					 struct ieee80211_mgmt *mgmt,
					 size_t len,
					 int reassoc)
{
1169
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1170
	struct ieee80211_local *local = sdata->local;
1171
	struct ieee80211_supported_band *sband;
1172
	struct sta_info *sta;
1173
	u32 rates, basic_rates;
1174 1175
	u16 capab_info, status_code, aid;
	struct ieee802_11_elems elems;
J
Johannes Berg 已提交
1176
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1177
	u8 *pos;
J
Johannes Berg 已提交
1178
	u32 changed = 0;
1179
	int i, j;
1180
	bool have_higher_than_11mbit = false, newsta = false;
J
Johannes Berg 已提交
1181
	u16 ap_ht_cap_flags;
1182 1183 1184 1185

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

1186
	if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
1187 1188
		return;

1189
	if (len < 24 + 6)
1190 1191
		return;

1192
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0)
1193 1194 1195 1196 1197 1198
		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);

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

1204 1205 1206 1207
	pos = mgmt->u.assoc_resp.variable;
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);

	if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
1208 1209
	    elems.timeout_int && elems.timeout_int_len == 5 &&
	    elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
1210
		u32 tu, ms;
1211
		tu = get_unaligned_le32(elems.timeout_int + 1);
1212 1213 1214 1215 1216
		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)
1217
			mod_timer(&ifmgd->timer,
1218 1219 1220 1221
				  jiffies + msecs_to_jiffies(ms));
		return;
	}

1222 1223
	if (status_code != WLAN_STATUS_SUCCESS) {
		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
1224
		       sdata->dev->name, status_code);
1225 1226 1227
		/* 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. */
1228
		ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1229 1230 1231
		return;
	}

1232 1233
	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
		printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
1234
		       "set\n", sdata->dev->name, aid);
1235 1236
	aid &= ~(BIT(15) | BIT(14));

1237 1238
	if (!elems.supp_rates) {
		printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
1239
		       sdata->dev->name);
1240 1241 1242
		return;
	}

1243
	printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
1244 1245
	ifmgd->aid = aid;
	ifmgd->ap_capab = capab_info;
1246

1247 1248 1249 1250 1251
	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);
1252

1253 1254
	rcu_read_lock();

1255
	/* Add STA entry for the AP */
1256
	sta = sta_info_get(local, ifmgd->bssid);
1257
	if (!sta) {
1258
		newsta = true;
1259

1260
		sta = sta_info_alloc(sdata, ifmgd->bssid, GFP_ATOMIC);
J
Johannes Berg 已提交
1261 1262
		if (!sta) {
			printk(KERN_DEBUG "%s: failed to alloc STA entry for"
1263
			       " the AP\n", sdata->dev->name);
1264
			rcu_read_unlock();
1265 1266
			return;
		}
1267

J
Johannes Berg 已提交
1268 1269
		/* update new sta with its last rx activity */
		sta->last_rx = jiffies;
1270 1271
	}

J
Johannes Berg 已提交
1272 1273 1274 1275 1276 1277 1278 1279 1280
	/*
	 * 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.
	 */
1281

J
Johannes Berg 已提交
1282 1283
	set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
			   WLAN_STA_AUTHORIZED);
1284

J
Johannes Berg 已提交
1285 1286 1287
	rates = 0;
	basic_rates = 0;
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1288

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

J
Johannes Berg 已提交
1293 1294 1295 1296
		if (rate > 110)
			have_higher_than_11mbit = true;

		for (j = 0; j < sband->n_bitrates; j++) {
1297
			if (sband->bitrates[j].bitrate == rate) {
J
Johannes Berg 已提交
1298
				rates |= BIT(j);
1299 1300 1301 1302
				if (is_basic)
					basic_rates |= BIT(j);
				break;
			}
1303 1304 1305
		}
	}

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

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

J
Johannes Berg 已提交
1313
		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;
			}
J
Johannes Berg 已提交
1320
		}
1321
	}
1322

J
Johannes Berg 已提交
1323
	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
J
Johannes Berg 已提交
1324
	sdata->vif.bss_conf.basic_rates = basic_rates;
J
Johannes Berg 已提交
1325 1326 1327 1328 1329 1330 1331

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

1333 1334
	/* 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 已提交
1335
		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
J
Johannes Berg 已提交
1336
				elems.ht_cap_elem, &sta->sta.ht_cap);
J
Johannes Berg 已提交
1337 1338

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

1340
	rate_control_rate_init(sta);
1341

1342
	if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
1343 1344
		set_sta_flags(sta, WLAN_STA_MFP);

1345
	if (elems.wmm_param)
J
Johannes Berg 已提交
1346
		set_sta_flags(sta, WLAN_STA_WME);
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360

	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)
1361
		ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
J
Johannes Berg 已提交
1362
					 elems.wmm_param_len);
1363

J
Johannes Berg 已提交
1364
	if (elems.ht_info_elem && elems.wmm_param &&
1365 1366
	    (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
	    !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
J
Johannes Berg 已提交
1367 1368 1369
		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
					       ap_ht_cap_flags);

J
Johannes Berg 已提交
1370 1371 1372 1373
	/* set AID and assoc capability,
	 * ieee80211_set_associated() will tell the driver */
	bss_conf->aid = aid;
	bss_conf->assoc_capability = capab_info;
1374
	ieee80211_set_associated(sdata, changed);
1375

1376
	ieee80211_associated(sdata);
1377
	cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
1378 1379 1380
}


1381 1382 1383 1384 1385 1386 1387 1388 1389
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;
1390
	struct ieee80211_bss *bss;
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
	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,
1404
					channel, beacon);
1405 1406 1407
	if (!bss)
		return;

S
Sujith 已提交
1408
	if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
1409
	    (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) {
S
Sujith 已提交
1410 1411 1412 1413 1414
		struct ieee80211_channel_sw_ie *sw_elem =
			(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
		ieee80211_process_chanswitch(sdata, sw_elem, bss);
	}

1415
	ieee80211_rx_bss_put(local, bss);
1416 1417 1418
}


1419
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1420 1421 1422 1423
					 struct ieee80211_mgmt *mgmt,
					 size_t len,
					 struct ieee80211_rx_status *rx_status)
{
1424 1425 1426
	size_t baselen;
	struct ieee802_11_elems elems;

1427 1428 1429
	if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
		return; /* ignore ProbeResp to foreign address */

1430 1431 1432 1433 1434 1435 1436
	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);

1437
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1438 1439 1440

	/* direct probe may be part of the association flow */
	if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
1441
	    &sdata->u.mgd.request)) {
1442 1443
		printk(KERN_DEBUG "%s direct probe responded\n",
		       sdata->dev->name);
1444
		ieee80211_authenticate(sdata);
1445
	}
1446 1447
}

1448
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1449 1450 1451 1452
				     struct ieee80211_mgmt *mgmt,
				     size_t len,
				     struct ieee80211_rx_status *rx_status)
{
1453
	struct ieee80211_if_managed *ifmgd;
1454 1455
	size_t baselen;
	struct ieee802_11_elems elems;
1456
	struct ieee80211_local *local = sdata->local;
1457
	u32 changed = 0;
1458
	bool erp_valid, directed_tim;
J
Johannes Berg 已提交
1459
	u8 erp_value = 0;
1460

1461 1462 1463 1464 1465 1466 1467
	/* 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);

1468
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
1469

1470
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1471 1472
		return;

1473 1474 1475 1476
	ifmgd = &sdata->u.mgd;

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

S
Sujith 已提交
1479 1480 1481
	if (rx_status->freq != local->hw.conf.channel->center_freq)
		return;

1482
	ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
1483 1484
				 elems.wmm_param_len);

1485
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
1486
		directed_tim = ieee80211_check_tim(&elems, ifmgd->aid);
1487

1488
		if (directed_tim) {
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
			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);
			}
1507 1508
		}
	}
J
Johannes Berg 已提交
1509 1510 1511 1512 1513 1514

	if (elems.erp_info && elems.erp_info_len >= 1) {
		erp_valid = true;
		erp_value = elems.erp_info[0];
	} else {
		erp_valid = false;
1515
	}
J
Johannes Berg 已提交
1516 1517 1518
	changed |= ieee80211_handle_bss_capability(sdata,
			le16_to_cpu(mgmt->u.beacon.capab_info),
			erp_valid, erp_value);
1519

1520

1521
	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
1522
	    !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED)) {
J
Johannes Berg 已提交
1523 1524 1525 1526 1527 1528
		struct sta_info *sta;
		struct ieee80211_supported_band *sband;
		u16 ap_ht_cap_flags;

		rcu_read_lock();

1529
		sta = sta_info_get(local, ifmgd->bssid);
J
Johannes Berg 已提交
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
		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);
1546 1547
	}

1548 1549 1550 1551 1552
	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);
1553 1554 1555 1556 1557 1558 1559

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

1562
	ieee80211_bss_info_change_notify(sdata, changed);
1563 1564
}

1565 1566 1567
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
					  struct sk_buff *skb,
					  struct ieee80211_rx_status *rx_status)
1568
{
1569
	struct ieee80211_local *local = sdata->local;
1570 1571 1572 1573
	struct ieee80211_mgmt *mgmt;
	u16 fc;

	if (skb->len < 24)
1574
		return RX_DROP_MONITOR;
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588

	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:
1589 1590 1591
		skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
		queue_work(local->hw.workqueue, &sdata->u.mgd.work);
		return RX_QUEUED;
1592 1593
	}

1594
	return RX_DROP_MONITOR;
1595 1596
}

1597
static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1598 1599 1600 1601 1602 1603 1604 1605 1606 1607
					 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);

1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631
	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;
1632 1633 1634 1635 1636
	}

	kfree_skb(skb);
}

J
Johannes Berg 已提交
1637
static void ieee80211_sta_timer(unsigned long data)
1638
{
J
Johannes Berg 已提交
1639 1640
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
1641
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1642
	struct ieee80211_local *local = sdata->local;
1643

1644 1645
	set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
	queue_work(local->hw.workqueue, &ifmgd->work);
1646 1647
}

1648
static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata)
1649
{
1650
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1651
	struct ieee80211_local *local = sdata->local;
1652 1653 1654 1655 1656 1657

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

1658
	ifmgd->wmm_last_param_set = -1; /* allow any WMM update */
1659 1660


1661 1662 1663 1664 1665 1666
	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;
1667
	else
1668 1669 1670 1671 1672 1673 1674
		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;
1675
	netif_tx_stop_all_queues(sdata->dev);
1676
	netif_carrier_off(sdata->dev);
1677 1678
}

1679
static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
1680
{
1681
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1682
	struct ieee80211_local *local = sdata->local;
1683
	struct ieee80211_bss *bss;
1684 1685
	u8 *bssid = ifmgd->bssid, *ssid = ifmgd->ssid;
	u8 ssid_len = ifmgd->ssid_len;
1686 1687 1688 1689
	u16 capa_mask = WLAN_CAPABILITY_ESS;
	u16 capa_val = WLAN_CAPABILITY_ESS;
	struct ieee80211_channel *chan = local->oper_channel;

1690
	if (ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL |
1691 1692 1693 1694 1695
			    IEEE80211_STA_AUTO_BSSID_SEL |
			    IEEE80211_STA_AUTO_CHANNEL_SEL)) {
		capa_mask |= WLAN_CAPABILITY_PRIVACY;
		if (sdata->default_key)
			capa_val |= WLAN_CAPABILITY_PRIVACY;
1696
	}
1697

1698
	if (ifmgd->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
1699 1700
		chan = NULL;

1701
	if (ifmgd->flags & IEEE80211_STA_AUTO_BSSID_SEL)
1702 1703
		bssid = NULL;

1704
	if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL) {
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
		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);
1715
		if (!(ifmgd->flags & IEEE80211_STA_SSID_SET))
1716 1717 1718 1719 1720
			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);
1721 1722
		if (sdata->u.mgd.mfp == IEEE80211_MFP_REQUIRED)
			sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
1723
		else
1724
			sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
1725

J
Johannes Berg 已提交
1726 1727 1728
		/* Send out direct probe if no probe resp was received or
		 * the one we have is outdated
		 */
1729 1730
		if (!bss->last_probe_resp ||
		    time_after(jiffies, bss->last_probe_resp
J
Johannes Berg 已提交
1731
					+ IEEE80211_SCAN_RESULT_EXPIRE))
1732
			ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
J
Johannes Berg 已提交
1733
		else
1734
			ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
1735

1736
		ieee80211_rx_bss_put(local, bss);
1737
		ieee80211_sta_reset_auth(sdata);
J
Johannes Berg 已提交
1738 1739
		return 0;
	} else {
1740 1741
		if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) {
			ifmgd->assoc_scan_tries++;
1742 1743 1744 1745
			/* XXX maybe racy? */
			if (local->scan_req)
				return -1;
			memcpy(local->int_scan_req.ssids[0].ssid,
1746 1747
			       ifmgd->ssid, IEEE80211_MAX_SSID_LEN);
			if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL)
1748
				local->int_scan_req.ssids[0].ssid_len = 0;
J
Johannes Berg 已提交
1749
			else
1750
				local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len;
1751 1752 1753 1754

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

1755 1756
			ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
			set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
1757
		} else {
1758 1759
			ifmgd->assoc_scan_tries = 0;
			ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1760
		}
J
Johannes Berg 已提交
1761 1762 1763 1764 1765 1766 1767 1768
	}
	return -1;
}


static void ieee80211_sta_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
1769
		container_of(work, struct ieee80211_sub_if_data, u.mgd.work);
J
Johannes Berg 已提交
1770
	struct ieee80211_local *local = sdata->local;
1771
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1772 1773 1774 1775 1776
	struct sk_buff *skb;

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

1777
	if (local->sw_scanning || local->hw_scanning)
J
Johannes Berg 已提交
1778 1779
		return;

1780
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
J
Johannes Berg 已提交
1781
		return;
1782
	ifmgd = &sdata->u.mgd;
1783

1784
	while ((skb = skb_dequeue(&ifmgd->skb_queue)))
J
Johannes Berg 已提交
1785 1786
		ieee80211_sta_rx_queued_mgmt(sdata, skb);

1787 1788 1789 1790
	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)) {
1791 1792 1793 1794 1795 1796 1797 1798
		/*
		 * 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 已提交
1799
		return;
1800 1801
	}

1802 1803
	if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request)) {
		if (ieee80211_sta_config_auth(sdata))
J
Johannes Berg 已提交
1804
			return;
1805 1806
		clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
	} else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request))
J
Johannes Berg 已提交
1807
		return;
1808

1809
	switch (ifmgd->state) {
J
Johannes Berg 已提交
1810 1811 1812
	case IEEE80211_STA_MLME_DISABLED:
		break;
	case IEEE80211_STA_MLME_DIRECT_PROBE:
1813
		ieee80211_direct_probe(sdata);
J
Johannes Berg 已提交
1814 1815
		break;
	case IEEE80211_STA_MLME_AUTHENTICATE:
1816
		ieee80211_authenticate(sdata);
J
Johannes Berg 已提交
1817 1818
		break;
	case IEEE80211_STA_MLME_ASSOCIATE:
1819
		ieee80211_associate(sdata);
J
Johannes Berg 已提交
1820 1821
		break;
	case IEEE80211_STA_MLME_ASSOCIATED:
1822
		ieee80211_associated(sdata);
J
Johannes Berg 已提交
1823 1824 1825 1826 1827 1828
		break;
	default:
		WARN_ON(1);
		break;
	}

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

1833
		ieee80211_set_disassoc(sdata, false, true,
J
Johannes Berg 已提交
1834 1835
					WLAN_REASON_UNSPECIFIED);
	}
1836 1837
}

J
Johannes Berg 已提交
1838 1839
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
1840
	if (sdata->vif.type == NL80211_IFTYPE_STATION)
J
Johannes Berg 已提交
1841
		queue_work(sdata->local->hw.workqueue,
1842
			   &sdata->u.mgd.work);
J
Johannes Berg 已提交
1843
}
1844

J
Johannes Berg 已提交
1845 1846
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1847
{
1848
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1849

1850 1851 1852 1853
	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 已提交
1854
		    (unsigned long) sdata);
1855
	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
J
Johannes Berg 已提交
1856
		    (unsigned long) sdata);
1857
	skb_queue_head_init(&ifmgd->skb_queue);
J
Johannes Berg 已提交
1858

1859 1860
	ifmgd->capab = WLAN_CAPABILITY_ESS;
	ifmgd->auth_algs = IEEE80211_AUTH_ALG_OPEN |
J
Johannes Berg 已提交
1861
		IEEE80211_AUTH_ALG_SHARED_KEY;
1862
	ifmgd->flags |= IEEE80211_STA_CREATE_IBSS |
J
Johannes Berg 已提交
1863 1864
		IEEE80211_STA_AUTO_BSSID_SEL |
		IEEE80211_STA_AUTO_CHANNEL_SEL;
1865
	if (sdata->local->hw.queues >= 4)
1866
		ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
1867 1868
}

J
Johannes Berg 已提交
1869
/* configuration hooks */
1870
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
1871
{
1872
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1873 1874
	struct ieee80211_local *local = sdata->local;

1875
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
J
Johannes Berg 已提交
1876
		return;
J
Johannes Berg 已提交
1877

1878
	if ((ifmgd->flags & (IEEE80211_STA_BSSID_SET |
J
Johannes Berg 已提交
1879
			     IEEE80211_STA_AUTO_BSSID_SEL)) &&
1880
	    (ifmgd->flags & (IEEE80211_STA_SSID_SET |
J
Johannes Berg 已提交
1881
			     IEEE80211_STA_AUTO_SSID_SEL))) {
J
Johannes Berg 已提交
1882

1883 1884
		if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
			ieee80211_set_disassoc(sdata, true, true,
J
Johannes Berg 已提交
1885
					       WLAN_REASON_DEAUTH_LEAVING);
J
Johannes Berg 已提交
1886

1887 1888
		set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
		queue_work(local->hw.workqueue, &ifmgd->work);
J
Johannes Berg 已提交
1889 1890
	}
}
J
Johannes Berg 已提交
1891

1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903
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 已提交
1904 1905
int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
{
1906
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1907

J
Johannes Berg 已提交
1908 1909 1910
	if (len > IEEE80211_MAX_SSID_LEN)
		return -EINVAL;

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

1913
	if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) {
1914 1915 1916 1917
		/*
		 * Do not use reassociation if SSID is changed (different ESS).
		 */
		ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1918 1919 1920
		memset(ifmgd->ssid, 0, sizeof(ifmgd->ssid));
		memcpy(ifmgd->ssid, ssid, len);
		ifmgd->ssid_len = len;
J
Johannes Berg 已提交
1921 1922
	}

1923
	return ieee80211_sta_commit(sdata);
J
Johannes Berg 已提交
1924 1925 1926 1927
}

int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
{
1928 1929 1930
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	memcpy(ssid, ifmgd->ssid, ifmgd->ssid_len);
	*len = ifmgd->ssid_len;
J
Johannes Berg 已提交
1931 1932 1933 1934 1935
	return 0;
}

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

1938
	if (is_valid_ether_addr(bssid)) {
1939 1940
		memcpy(ifmgd->bssid, bssid, ETH_ALEN);
		ifmgd->flags |= IEEE80211_STA_BSSID_SET;
1941
	} else {
1942 1943
		memset(ifmgd->bssid, 0, ETH_ALEN);
		ifmgd->flags &= ~IEEE80211_STA_BSSID_SET;
1944 1945 1946 1947
	}

	if (netif_running(sdata->dev)) {
		if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) {
J
Johannes Berg 已提交
1948 1949 1950 1951
			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
			       "the low-level driver\n", sdata->dev->name);
		}
	}
J
Johannes Berg 已提交
1952

1953
	return ieee80211_sta_commit(sdata);
J
Johannes Berg 已提交
1954 1955 1956 1957
}

int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len)
{
1958
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1959

1960
	kfree(ifmgd->extra_ie);
J
Johannes Berg 已提交
1961
	if (len == 0) {
1962 1963
		ifmgd->extra_ie = NULL;
		ifmgd->extra_ie_len = 0;
J
Johannes Berg 已提交
1964 1965
		return 0;
	}
1966 1967 1968
	ifmgd->extra_ie = kmalloc(len, GFP_KERNEL);
	if (!ifmgd->extra_ie) {
		ifmgd->extra_ie_len = 0;
J
Johannes Berg 已提交
1969 1970
		return -ENOMEM;
	}
1971 1972
	memcpy(ifmgd->extra_ie, ie, len);
	ifmgd->extra_ie_len = len;
J
Johannes Berg 已提交
1973
	return 0;
J
Johannes Berg 已提交
1974 1975
}

1976
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
1977
{
1978
	printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
1979
	       sdata->dev->name, reason);
1980

1981
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1982 1983
		return -EINVAL;

1984
	ieee80211_set_disassoc(sdata, true, true, reason);
1985 1986 1987
	return 0;
}

1988
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
1989
{
1990
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1991

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

1995
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1996 1997
		return -EINVAL;

1998 1999
	if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED))
		return -ENOLINK;
2000

2001
	ieee80211_set_disassoc(sdata, false, true, reason);
2002 2003
	return 0;
}
2004

J
Johannes Berg 已提交
2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015
/* 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();
}
2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036

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);
2037
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
2038 2039 2040 2041

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

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

2045
	local->hw.conf.flags |= IEEE80211_CONF_PS;
2046 2047 2048 2049 2050 2051 2052 2053 2054
	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);
}
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087

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