mlme.c 62.4 KB
Newer Older
1
2
/*
 * BSS client mode implementation
3
 * Copyright 2003-2008, Jouni Malinen <j@w1.fi>
4
5
6
7
8
9
10
11
12
13
 * Copyright 2004, Instant802 Networks, Inc.
 * Copyright 2005, Devicescape Software, Inc.
 * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

14
#include <linux/delay.h>
15
16
17
18
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
19
#include <linux/rtnetlink.h>
20
#include <linux/pm_qos_params.h>
21
#include <linux/crc32.h>
22
#include <net/mac80211.h>
23
#include <asm/unaligned.h>
Johannes Berg's avatar
Johannes Berg committed
24

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

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

37
38
39
#define TMR_RUNNING_TIMER	0
#define TMR_RUNNING_CHANSW	1

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

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

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

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

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

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

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

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

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

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

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

	return count;
}

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

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

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

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

	if (enable_ht) {
		channel_type = NL80211_CHAN_HT20;

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

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

	local->oper_channel_type = channel_type;

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

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

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

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

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

	return changed;
}

184
185
/* frame sending functions */

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

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

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

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

	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
			capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
			capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
	}

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

227
228
229
230
231
	/* get all rates supported by the device and the AP as
	 * some APs don't like getting a superset of their rates
	 * in the association request (e.g. D-Link DAP 1353 in
	 * b-only mode) */
	rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
232

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

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

243
	if (!is_zero_ether_addr(wk->prev_bssid)) {
244
245
246
247
248
249
		skb_put(skb, 10);
		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						  IEEE80211_STYPE_REASSOC_REQ);
		mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
		mgmt->u.reassoc_req.listen_interval =
				cpu_to_le16(local->hw.conf.listen_interval);
250
		memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid,
251
252
253
254
255
256
		       ETH_ALEN);
	} else {
		skb_put(skb, 4);
		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						  IEEE80211_STYPE_ASSOC_REQ);
		mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
257
		mgmt->u.assoc_req.listen_interval =
258
259
260
261
				cpu_to_le16(local->hw.conf.listen_interval);
	}

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

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

	len = sband->n_bitrates;
	pos = skb_put(skb, supp_rates_len + 2);
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos++ = supp_rates_len;

	count = 0;
	for (i = 0; i < sband->n_bitrates; i++) {
		if (BIT(i) & rates) {
			int rate = sband->bitrates[i].bitrate;
			*pos++ = (u8) (rate / 5);
			if (++count == 8)
				break;
		}
	}

	if (rates_len > count) {
		pos = skb_put(skb, rates_len - count + 2);
		*pos++ = WLAN_EID_EXT_SUPP_RATES;
		*pos++ = rates_len - count;

		for (i++; i < sband->n_bitrates; i++) {
			if (BIT(i) & rates) {
				int rate = sband->bitrates[i].bitrate;
				*pos++ = (u8) (rate / 5);
			}
		}
	}

	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
		/* 1. power capabilities */
		pos = skb_put(skb, 4);
		*pos++ = WLAN_EID_PWR_CAPABILITY;
		*pos++ = 2;
		*pos++ = 0; /* min tx power */
		*pos++ = local->hw.conf.channel->max_power; /* max tx power */

		/* 2. supported channels */
		/* TODO: get this in reg domain format */
		pos = skb_put(skb, 2 * sband->n_channels + 2);
		*pos++ = WLAN_EID_SUPPORTED_CHANNELS;
		*pos++ = 2 * sband->n_channels;
		for (i = 0; i < sband->n_channels; i++) {
			*pos++ = ieee80211_frequency_to_channel(
					sband->channels[i].center_freq);
			*pos++ = 1; /* one channel in the subband*/
		}
	}

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

325
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
326
327
328
329
330
331
332
333
334
335
336
337
338
		pos = skb_put(skb, 9);
		*pos++ = WLAN_EID_VENDOR_SPECIFIC;
		*pos++ = 7; /* len */
		*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
		*pos++ = 0x50;
		*pos++ = 0xf2;
		*pos++ = 2; /* WME */
		*pos++ = 0; /* WME info */
		*pos++ = 1; /* WME ver */
		*pos++ = 0;
	}

	/* wmm support is a must to HT */
339
340
341
342
343
344
	/*
	 * IEEE802.11n does not allow TKIP/WEP as pairwise
	 * ciphers in HT mode. We still associate in non-ht
	 * mode (11a/b/g) if any one of these ciphers is
	 * configured as pairwise.
	 */
345
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
346
	    sband->ht_cap.ht_supported &&
347
	    (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) &&
348
	    ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
349
	    (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
350
351
352
		struct ieee80211_ht_info *ht_info =
			(struct ieee80211_ht_info *)(ht_ie + 2);
		u16 cap = sband->ht_cap.cap;
353
354
355
		__le16 tmp;
		u32 flags = local->hw.conf.channel->flags;

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

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

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


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

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

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

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

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

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

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

	ieee80211_tx_skb(sdata, skb, 0);
}

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
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);
}

487
488
489
490
491
492
493
494
495
496
/* spectrum management related things */
static void ieee80211_chswitch_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

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

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

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

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

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

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

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

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

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

536
537
538
	ASSERT_MGD_MTX(ifmgd);

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

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

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

	if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
		return;

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

	sdata->local->csa_channel = new_ch;

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

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

	if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
		return;

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

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

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

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

602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
	if (conf->dynamic_ps_timeout > 0 &&
	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
		mod_timer(&local->dynamic_ps_timer, jiffies +
			  msecs_to_jiffies(conf->dynamic_ps_timeout));
	} else {
		if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
			ieee80211_send_nullfunc(local, sdata, 1);
		conf->flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}
}

static void ieee80211_change_ps(struct ieee80211_local *local)
{
	struct ieee80211_conf *conf = &local->hw.conf;

	if (local->ps_sdata) {
		ieee80211_enable_ps(local, local->ps_sdata);
	} else if (conf->flags & IEEE80211_CONF_PS) {
		conf->flags &= ~IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
		del_timer_sync(&local->dynamic_ps_timer);
		cancel_work_sync(&local->dynamic_ps_enable_work);
	}
}

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

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

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

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

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

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

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

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

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

	ieee80211_change_ps(local);
}

void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     dynamic_ps_disable_work);

	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}

	ieee80211_wake_queues_by_reason(&local->hw,
					IEEE80211_QUEUE_STOP_REASON_PS);
}

void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     dynamic_ps_enable_work);
	struct ieee80211_sub_if_data *sdata = local->ps_sdata;

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

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

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

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

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

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

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

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

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

	if (!wmm_param)
		return;

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

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

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

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

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

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

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

	return changed;
}

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

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

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

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

856
	ieee80211_led_assoc(local, 1);
857

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

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

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

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

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

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

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

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

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

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

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

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

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

925

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

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

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

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

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

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

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

964
	return RX_MGMT_NONE;
965
966
}

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

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

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

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

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

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

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

1003
1004
1005
	changed |= ieee80211_reset_erp_info(sdata);

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

1009
1010
	ieee80211_set_wmm_default(sdata);

1011
1012
	ieee80211_recalc_idle(local);

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

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

1019
1020
	local->power_constr_level = 0;

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

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

1029
	ieee80211_hw_config(local, config_changed);
1030
1031
1032

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

	rcu_read_lock();

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

	sta_info_unlink(&sta);

	rcu_read_unlock();

	sta_info_destroy(sta);
1048
}
1049

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

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

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

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

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

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

1085
	return RX_MGMT_NONE;
1086
1087
}

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_hdr *hdr)
{
	/*
	 * We can postpone the mgd.timer whenever receiving unicast frames
	 * from AP because we know that the connection is working both ways
	 * at that time. But multicast frames (and hence also beacons) must
	 * be ignored here, because we need to trigger the timer during
	 * data idle periods for sending the periodical probe request to
	 * the AP.
	 */
	if (!is_multicast_ether_addr(hdr->addr1))
		mod_timer(&sdata->u.mgd.timer,
			  jiffies + IEEE80211_MONITORING_INTERVAL);
}
1103

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

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
	/*
	 * The driver has already reported this event and we have
	 * already sent a probe request. Maybe the AP died and the
	 * driver keeps reporting until we disassociate... We have
	 * to ignore that because otherwise we would continually
	 * reset the timer and never check whether we received a
	 * probe response!
	 */
	if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
		return;

1123
1124
1125
1126
1127
	mutex_lock(&ifmgd->mtx);

	if (!ifmgd->associated)
		goto out;

1128
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1129
1130
1131
	if (net_ratelimit())
		printk(KERN_DEBUG "%s: driver reports beacon loss from AP "
		       "- sending probe request\n", sdata->dev->name);
1132
#endif
1133
1134

	ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
1135
1136
1137
1138
1139

	mutex_lock(&sdata->local->iflist_mtx);
	ieee80211_recalc_ps(sdata->local, -1);
	mutex_unlock(&sdata->local->iflist_mtx);

1140
1141
1142
	ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID);
	ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
				 ssid + 2, ssid[1], NULL, 0);
1143

1144
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
1145
1146
 out:
	mutex_unlock(&ifmgd->mtx);
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
}

void ieee80211_beacon_loss(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);

	queue_work(sdata->local->hw.workqueue,
		   &sdata->u.mgd.beacon_loss_work);
}
EXPORT_SYMBOL(ieee80211_beacon_loss);

1158
1159
static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_mgd_work *wk)
1160
{
1161
	wk->state = IEEE80211_MGD_STATE_IDLE;
1162
	printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
1163
1164
1165
}


1166
static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1167
				     struct ieee80211_mgd_work *wk,
1168
1169
1170
1171
1172
1173
1174
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u8 *pos;
	struct ieee802_11_elems elems;

	pos = mgmt->u.auth.variable;
1175
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1176
	if (!elems.challenge)
1177
		return;
1178
	ieee80211_send_auth(sdata, 3, wk->auth_alg,
1179
			    elems.challenge - 2, elems.challenge_len + 2,
1180
1181
			    wk->bss->cbss.bssid, 1);
	wk->auth_transaction = 4;
1182
1183
}

1184
1185
1186
1187
static enum rx_mgmt_action __must_check
ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
		       struct ieee80211_mgd_work *wk,
		       struct ieee80211_mgmt *mgmt, size_t len)
1188
1189
1190
{
	u16 auth_alg, auth_transaction, status_code;

1191
1192
	if (wk->state != IEEE80211_MGD_STATE_AUTH)
		return RX_MGMT_NONE;
1193

1194
	if (len < 24 + 6)
1195
		return RX_MGMT_NONE;
1196