mlme.c 57.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 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 1089
		break;
	case WLAN_AUTH_SHARED_KEY:
1090 1091
		if (ifmgd->auth_transaction == 4)
			ieee80211_auth_completed(sdata);
1092
		else
1093
			ieee80211_auth_challenge(sdata, mgmt, len);
1094 1095 1096 1097 1098
		break;
	}
}


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

1106
	if (len < 24 + 2)
1107 1108
		return;

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

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

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

1118 1119 1120 1121 1122
	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 +
1123 1124 1125
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1126 1127
	ieee80211_set_disassoc(sdata, true, false, 0);
	ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
1128 1129 1130
}


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

1138
	if (len < 24 + 2)
1139 1140
		return;

1141
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN))
1142 1143 1144 1145
		return;

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

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

1150 1151 1152
	if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
		ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
		mod_timer(&ifmgd->timer, jiffies +
1153 1154 1155
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1156
	ieee80211_set_disassoc(sdata, false, false, reason_code);
1157 1158 1159
}


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

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

1182
	if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
1183 1184
		return;

1185
	if (len < 24 + 6)
1186 1187
		return;

1188
	if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0)
1189 1190 1191 1192 1193 1194
		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);

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

1200 1201 1202 1203
	pos = mgmt->u.assoc_resp.variable;
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);

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

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

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

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

1239
	printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
1240 1241
	ifmgd->aid = aid;
	ifmgd->ap_capab = capab_info;
1242

1243 1244 1245 1246 1247
	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);
1248

1249 1250
	rcu_read_lock();

1251
	/* Add STA entry for the AP */
1252
	sta = sta_info_get(local, ifmgd->bssid);
1253
	if (!sta) {
1254
		newsta = true;
1255

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

J
Johannes Berg 已提交
1264 1265
		/* update new sta with its last rx activity */
		sta->last_rx = jiffies;
1266 1267
	}

J
Johannes Berg 已提交
1268 1269 1270 1271 1272 1273 1274 1275 1276
	/*
	 * 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.
	 */
1277

J
Johannes Berg 已提交
1278 1279
	set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
			   WLAN_STA_AUTHORIZED);
1280

J
Johannes Berg 已提交
1281 1282 1283
	rates = 0;
	basic_rates = 0;
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1284

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

J
Johannes Berg 已提交
1289 1290 1291 1292
		if (rate > 110)
			have_higher_than_11mbit = true;

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

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

J
Johannes Berg 已提交
1306 1307
		if (rate > 110)
			have_higher_than_11mbit = true;
1308

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

J
Johannes Berg 已提交
1319
	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
J
Johannes Berg 已提交
1320
	sdata->vif.bss_conf.basic_rates = basic_rates;
J
Johannes Berg 已提交
1321 1322 1323 1324 1325 1326 1327

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

1329 1330
	/* 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 已提交
1331
		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
J
Johannes Berg 已提交
1332
				elems.ht_cap_elem, &sta->sta.ht_cap);
J
Johannes Berg 已提交
1333 1334

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

1336
	rate_control_rate_init(sta);
1337

1338
	if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
1339 1340
		set_sta_flags(sta, WLAN_STA_MFP);

1341
	if (elems.wmm_param)
J
Johannes Berg 已提交
1342
		set_sta_flags(sta, WLAN_STA_WME);
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356

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

J
Johannes Berg 已提交
1360
	if (elems.ht_info_elem && elems.wmm_param &&
1361 1362
	    (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
	    !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
J
Johannes Berg 已提交
1363 1364 1365
		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
					       ap_ht_cap_flags);

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

1372
	ieee80211_associated(sdata);
1373 1374 1375
}


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

S
Sujith 已提交
1403
	if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
1404
	    (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) {
S
Sujith 已提交
1405 1406 1407 1408 1409
		struct ieee80211_channel_sw_ie *sw_elem =
			(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
		ieee80211_process_chanswitch(sdata, sw_elem, bss);
	}

1410
	ieee80211_rx_bss_put(local, bss);
1411 1412 1413
}


1414
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1415 1416 1417 1418
					 struct ieee80211_mgmt *mgmt,
					 size_t len,
					 struct ieee80211_rx_status *rx_status)
{
1419 1420 1421
	size_t baselen;
	struct ieee802_11_elems elems;

1422 1423 1424
	if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
		return; /* ignore ProbeResp to foreign address */

1425 1426 1427 1428 1429 1430 1431
	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);

1432
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1433 1434 1435

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

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

1456 1457 1458 1459 1460 1461 1462
	/* 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);

1463
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
1464

1465
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1466 1467
		return;

1468 1469 1470 1471
	ifmgd = &sdata->u.mgd;

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

S
Sujith 已提交
1474 1475 1476
	if (rx_status->freq != local->hw.conf.channel->center_freq)
		return;

1477
	ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
1478 1479
				 elems.wmm_param_len);

1480
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
1481
		directed_tim = ieee80211_check_tim(&elems, ifmgd->aid);
1482

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

	if (elems.erp_info && elems.erp_info_len >= 1) {
		erp_valid = true;
		erp_value = elems.erp_info[0];
	} else {
		erp_valid = false;
1510
	}
J
Johannes Berg 已提交
1511 1512 1513
	changed |= ieee80211_handle_bss_capability(sdata,
			le16_to_cpu(mgmt->u.beacon.capab_info),
			erp_valid, erp_value);
1514

1515

1516
	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
1517
	    !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED)) {
J
Johannes Berg 已提交
1518 1519 1520 1521 1522 1523
		struct sta_info *sta;
		struct ieee80211_supported_band *sband;
		u16 ap_ht_cap_flags;

		rcu_read_lock();

1524
		sta = sta_info_get(local, ifmgd->bssid);
J
Johannes Berg 已提交
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
		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);
1541 1542
	}

1543 1544 1545 1546 1547
	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);
1548 1549 1550 1551 1552 1553 1554

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

1557
	ieee80211_bss_info_change_notify(sdata, changed);
1558 1559
}

1560 1561 1562
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
					  struct sk_buff *skb,
					  struct ieee80211_rx_status *rx_status)
1563
{
1564
	struct ieee80211_local *local = sdata->local;
1565 1566 1567 1568
	struct ieee80211_mgmt *mgmt;
	u16 fc;

	if (skb->len < 24)
1569
		return RX_DROP_MONITOR;
1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583

	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:
1584 1585 1586
		skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
		queue_work(local->hw.workqueue, &sdata->u.mgd.work);
		return RX_QUEUED;
1587 1588
	}

1589
	return RX_DROP_MONITOR;
1590 1591
}

1592
static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602
					 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);

1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626
	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;
1627 1628 1629 1630 1631
	}

	kfree_skb(skb);
}

J
Johannes Berg 已提交
1632
static void ieee80211_sta_timer(unsigned long data)
1633
{
J
Johannes Berg 已提交
1634 1635
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
1636
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1637
	struct ieee80211_local *local = sdata->local;
1638

1639 1640
	set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
	queue_work(local->hw.workqueue, &ifmgd->work);
1641 1642
}

1643
static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata)
1644
{
1645
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1646
	struct ieee80211_local *local = sdata->local;
1647 1648 1649 1650 1651 1652

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

1653
	ifmgd->wmm_last_param_set = -1; /* allow any WMM update */
1654 1655


1656 1657 1658 1659 1660 1661
	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;
1662
	else
1663 1664 1665 1666 1667 1668 1669
		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;
1670
	netif_tx_stop_all_queues(sdata->dev);
1671
	netif_carrier_off(sdata->dev);
1672 1673
}

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

1685
	if (ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL |
1686 1687 1688 1689 1690
			    IEEE80211_STA_AUTO_BSSID_SEL |
			    IEEE80211_STA_AUTO_CHANNEL_SEL)) {
		capa_mask |= WLAN_CAPABILITY_PRIVACY;
		if (sdata->default_key)
			capa_val |= WLAN_CAPABILITY_PRIVACY;
1691
	}
1692

1693
	if (ifmgd->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
1694 1695
		chan = NULL;

1696
	if (ifmgd->flags & IEEE80211_STA_AUTO_BSSID_SEL)
1697 1698
		bssid = NULL;

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

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

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

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

1750 1751
			ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
			set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
1752
		} else {
1753 1754
			ifmgd->assoc_scan_tries = 0;
			ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1755
		}
J
Johannes Berg 已提交
1756 1757 1758 1759 1760 1761 1762 1763
	}
	return -1;
}


static void ieee80211_sta_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
1764
		container_of(work, struct ieee80211_sub_if_data, u.mgd.work);
J
Johannes Berg 已提交
1765
	struct ieee80211_local *local = sdata->local;
1766
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1767 1768 1769 1770 1771
	struct sk_buff *skb;

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

1772
	if (local->sw_scanning || local->hw_scanning)
J
Johannes Berg 已提交
1773 1774
		return;

1775
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
J
Johannes Berg 已提交
1776
		return;
1777
	ifmgd = &sdata->u.mgd;
1778

1779
	while ((skb = skb_dequeue(&ifmgd->skb_queue)))
J
Johannes Berg 已提交
1780 1781
		ieee80211_sta_rx_queued_mgmt(sdata, skb);

1782 1783 1784 1785
	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)) {
1786 1787 1788 1789 1790 1791 1792 1793
		/*
		 * 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 已提交
1794
		return;
1795 1796
	}

1797 1798
	if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request)) {
		if (ieee80211_sta_config_auth(sdata))
J
Johannes Berg 已提交
1799
			return;
1800 1801
		clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
	} else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request))
J
Johannes Berg 已提交
1802
		return;
1803

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

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

1828
		ieee80211_set_disassoc(sdata, false, true,
J
Johannes Berg 已提交
1829 1830
					WLAN_REASON_UNSPECIFIED);
	}
1831 1832
}

J
Johannes Berg 已提交
1833 1834
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
1835
	if (sdata->vif.type == NL80211_IFTYPE_STATION)
J
Johannes Berg 已提交
1836
		queue_work(sdata->local->hw.workqueue,
1837
			   &sdata->u.mgd.work);
J
Johannes Berg 已提交
1838
}
1839

J
Johannes Berg 已提交
1840 1841
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1842
{
1843
	struct ieee80211_if_managed *ifmgd;
J
Johannes Berg 已提交
1844

1845 1846 1847 1848
	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 已提交
1849
		    (unsigned long) sdata);
1850
	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
J
Johannes Berg 已提交
1851
		    (unsigned long) sdata);
1852
	skb_queue_head_init(&ifmgd->skb_queue);
J
Johannes Berg 已提交
1853

1854 1855
	ifmgd->capab = WLAN_CAPABILITY_ESS;
	ifmgd->auth_algs = IEEE80211_AUTH_ALG_OPEN |
J
Johannes Berg 已提交
1856
		IEEE80211_AUTH_ALG_SHARED_KEY;
1857
	ifmgd->flags |= IEEE80211_STA_CREATE_IBSS |
J
Johannes Berg 已提交
1858 1859
		IEEE80211_STA_AUTO_BSSID_SEL |
		IEEE80211_STA_AUTO_CHANNEL_SEL;
1860
	if (sdata->local->hw.queues >= 4)
1861
		ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
1862 1863
}

J
Johannes Berg 已提交
1864
/* configuration hooks */
1865
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
J
Johannes Berg 已提交
1866
{
1867
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
J
Johannes Berg 已提交
1868 1869
	struct ieee80211_local *local = sdata->local;

1870
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
J
Johannes Berg 已提交
1871
		return;
J
Johannes Berg 已提交
1872

1873
	if ((ifmgd->flags & (IEEE80211_STA_BSSID_SET |
J
Johannes Berg 已提交
1874
			     IEEE80211_STA_AUTO_BSSID_SEL)) &&
1875
	    (ifmgd->flags & (IEEE80211_STA_SSID_SET |
J
Johannes Berg 已提交
1876
			     IEEE80211_STA_AUTO_SSID_SEL))) {
J
Johannes Berg 已提交
1877

1878 1879
		if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
			ieee80211_set_disassoc(sdata, true, true,
J
Johannes Berg 已提交
1880
					       WLAN_REASON_DEAUTH_LEAVING);
J
Johannes Berg 已提交
1881

1882 1883
		set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
		queue_work(local->hw.workqueue, &ifmgd->work);
J
Johannes Berg 已提交
1884 1885
	}
}
J
Johannes Berg 已提交
1886

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

J
Johannes Berg 已提交
1903 1904 1905
	if (len > IEEE80211_MAX_SSID_LEN)
		return -EINVAL;

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

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

1918
	return ieee80211_sta_commit(sdata);
J
Johannes Berg 已提交
1919 1920 1921 1922
}

int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
{
1923 1924 1925
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	memcpy(ssid, ifmgd->ssid, ifmgd->ssid_len);
	*len = ifmgd->ssid_len;
J
Johannes Berg 已提交
1926 1927 1928 1929 1930
	return 0;
}

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

1933
	if (is_valid_ether_addr(bssid)) {
1934 1935
		memcpy(ifmgd->bssid, bssid, ETH_ALEN);
		ifmgd->flags |= IEEE80211_STA_BSSID_SET;
1936
	} else {
1937 1938
		memset(ifmgd->bssid, 0, ETH_ALEN);
		ifmgd->flags &= ~IEEE80211_STA_BSSID_SET;
1939 1940 1941 1942
	}

	if (netif_running(sdata->dev)) {
		if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) {
J
Johannes Berg 已提交
1943 1944 1945 1946
			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
			       "the low-level driver\n", sdata->dev->name);
		}
	}
J
Johannes Berg 已提交
1947

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

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

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

1971
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
1972
{
1973
	printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
1974
	       sdata->dev->name, reason);
1975

1976
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1977 1978
		return -EINVAL;

1979
	ieee80211_set_disassoc(sdata, true, true, reason);
1980 1981 1982
	return 0;
}

1983
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
1984
{
1985
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1986

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

1990
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1991 1992
		return -EINVAL;

1993 1994
	if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED))
		return -ENOLINK;
1995

1996
	ieee80211_set_disassoc(sdata, false, true, reason);
1997 1998
	return 0;
}
1999

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

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);
2032
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
2033 2034 2035 2036

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

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

2040
	local->hw.conf.flags |= IEEE80211_CONF_PS;
2041 2042 2043 2044 2045 2046 2047 2048 2049
	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);
}
2050 2051 2052 2053 2054 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

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