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

14
#include <linux/delay.h>
15 16 17 18 19 20
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <linux/random.h>
#include <linux/etherdevice.h>
21
#include <linux/rtnetlink.h>
22 23
#include <net/iw_handler.h>
#include <net/mac80211.h>
24
#include <asm/unaligned.h>
J
Johannes Berg 已提交
25

26
#include "ieee80211_i.h"
J
Johannes Berg 已提交
27 28
#include "rate.h"
#include "led.h"
29

30
#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2
31 32 33 34 35 36 37 38 39
#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)
#define IEEE80211_SCAN_INTERVAL (2 * HZ)
#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
40
#define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ)
41 42 43 44 45 46 47

#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)

#define IEEE80211_IBSS_MAX_STA_ENTRIES 128


48 49
/* utils */
static int ecw2cw(int ecw)
J
Johannes Berg 已提交
50
{
51
	return (1 << ecw) - 1;
J
Johannes Berg 已提交
52 53
}

54
static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie)
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
{
	u8 *end, *pos;

	pos = bss->ies;
	if (pos == NULL)
		return NULL;
	end = pos + bss->ies_len;

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

	return NULL;
}

74
static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
75
				      struct ieee80211_supported_band *sband,
76
				      u32 *rates)
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
{
	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 已提交
95
/* also used by mesh code */
96
u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
J
Johannes Berg 已提交
97 98
			    struct ieee802_11_elems *elems,
			    enum ieee80211_band band)
J
Johannes Berg 已提交
99
{
J
Johannes Berg 已提交
100 101 102
	struct ieee80211_supported_band *sband;
	struct ieee80211_rate *bitrates;
	size_t num_rates;
103
	u32 supp_rates;
J
Johannes Berg 已提交
104 105
	int i, j;
	sband = local->hw.wiphy->bands[band];
J
Johannes Berg 已提交
106

J
Johannes Berg 已提交
107 108 109
	if (!sband) {
		WARN_ON(1);
		sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
J
Johannes Berg 已提交
110 111
	}

J
Johannes Berg 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
	bitrates = sband->bitrates;
	num_rates = sband->n_bitrates;
	supp_rates = 0;
	for (i = 0; i < elems->supp_rates_len +
		     elems->ext_supp_rates_len; i++) {
		u8 rate = 0;
		int own_rate;
		if (i < elems->supp_rates_len)
			rate = elems->supp_rates[i];
		else if (elems->ext_supp_rates)
			rate = elems->ext_supp_rates
				[i - elems->supp_rates_len];
		own_rate = 5 * (rate & 0x7f);
		for (j = 0; j < num_rates; j++)
			if (bitrates[j].bitrate == own_rate)
				supp_rates |= BIT(j);
	}
	return supp_rates;
J
Johannes Berg 已提交
130 131
}

J
Johannes Berg 已提交
132 133
/* frame sending functions */

134 135 136 137 138 139
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);
}

J
Johannes Berg 已提交
140
/* also used by scanning code */
141 142
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
			      u8 *ssid, size_t ssid_len)
J
Johannes Berg 已提交
143 144 145 146 147 148 149 150
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_supported_band *sband;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
	u8 *pos, *supp_rates, *esupp_rates = NULL;
	int i;

151 152
	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 +
			    sdata->u.sta.ie_probereq_len);
J
Johannes Berg 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
		       "request\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_PROBE_REQ);
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
	if (dst) {
		memcpy(mgmt->da, dst, ETH_ALEN);
		memcpy(mgmt->bssid, dst, ETH_ALEN);
	} else {
		memset(mgmt->da, 0xff, ETH_ALEN);
		memset(mgmt->bssid, 0xff, ETH_ALEN);
	}
	pos = skb_put(skb, 2 + ssid_len);
	*pos++ = WLAN_EID_SSID;
	*pos++ = ssid_len;
	memcpy(pos, ssid, ssid_len);

	supp_rates = skb_put(skb, 2);
	supp_rates[0] = WLAN_EID_SUPP_RATES;
	supp_rates[1] = 0;
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

	for (i = 0; i < sband->n_bitrates; i++) {
		struct ieee80211_rate *rate = &sband->bitrates[i];
		if (esupp_rates) {
			pos = skb_put(skb, 1);
			esupp_rates[1]++;
		} else if (supp_rates[1] == 8) {
			esupp_rates = skb_put(skb, 3);
			esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
			esupp_rates[1] = 1;
			pos = &esupp_rates[2];
		} else {
			pos = skb_put(skb, 1);
			supp_rates[1]++;
		}
		*pos = rate->bitrate / 5;
	}

199 200 201
	add_extra_ies(skb, sdata->u.sta.ie_probereq,
		      sdata->u.sta.ie_probereq_len);

J
Johannes Berg 已提交
202
	ieee80211_tx_skb(sdata, skb, 0);
J
Johannes Berg 已提交
203 204
}

J
Johannes Berg 已提交
205 206 207 208 209 210 211 212 213 214
static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
				struct ieee80211_if_sta *ifsta,
				int transaction, u8 *extra, size_t extra_len,
				int encrypt)
{
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
215 216
			    sizeof(*mgmt) + 6 + extra_len +
			    sdata->u.sta.ie_auth_len);
J
Johannes Berg 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
		       "frame\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
	memset(mgmt, 0, 24 + 6);
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_AUTH);
	if (encrypt)
		mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
	mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
	mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
	ifsta->auth_transaction = transaction + 1;
	mgmt->u.auth.status_code = cpu_to_le16(0);
	if (extra)
		memcpy(skb_put(skb, extra_len), extra, extra_len);
239
	add_extra_ies(skb, sdata->u.sta.ie_auth, sdata->u.sta.ie_auth_len);
J
Johannes Berg 已提交
240 241 242 243

	ieee80211_tx_skb(sdata, skb, encrypt);
}

244 245 246 247 248 249
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
				 struct ieee80211_if_sta *ifsta)
{
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
250
	u8 *pos, *ies, *ht_ie, *e_ies;
251 252
	int i, len, count, rates_len, supp_rates_len;
	u16 capab;
253
	struct ieee80211_bss *bss;
254 255
	int wmm = 0;
	struct ieee80211_supported_band *sband;
256
	u32 rates = 0;
257 258 259 260 261 262 263 264 265
	size_t e_ies_len;

	if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
		e_ies = sdata->u.sta.ie_reassocreq;
		e_ies_len = sdata->u.sta.ie_reassocreq_len;
	} else {
		e_ies = sdata->u.sta.ie_assocreq;
		e_ies_len = sdata->u.sta.ie_assocreq_len;
	}
266 267 268

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
			    sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
269
			    ifsta->ssid_len + e_ies_len);
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 320 321 322 323 324 325 326 327 328 329 330 331 332
	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];

	capab = ifsta->capab;

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

	bss = ieee80211_rx_bss_get(local, ifsta->bssid,
				   local->hw.conf.channel->center_freq,
				   ifsta->ssid, ifsta->ssid_len);
	if (bss) {
		if (bss->capability & WLAN_CAPABILITY_PRIVACY)
			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);

		if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
		    (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);
	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);

	if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
		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);
		memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
		       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);
333
		mgmt->u.assoc_req.listen_interval =
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
	ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
	*pos++ = WLAN_EID_SSID;
	*pos++ = ifsta->ssid_len;
	memcpy(pos, ifsta->ssid, ifsta->ssid_len);

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

	if (ifsta->extra_ie) {
		pos = skb_put(skb, ifsta->extra_ie_len);
		memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
	}

	if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
		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 */
415 416 417 418 419 420
	/*
	 * 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.
	 */
421
	if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
J
Johannes Berg 已提交
422 423
	    sband->ht_cap.ht_supported &&
	    (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
424 425
	    ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
	    (!(ifsta->flags & IEEE80211_STA_TKIP_WEP_USED))) {
J
Johannes Berg 已提交
426 427 428
		struct ieee80211_ht_info *ht_info =
			(struct ieee80211_ht_info *)(ht_ie + 2);
		u16 cap = sband->ht_cap.cap;
429 430 431
		__le16 tmp;
		u32 flags = local->hw.conf.channel->flags;

J
Johannes Berg 已提交
432 433
		switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
434
			if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
J
Johannes Berg 已提交
435
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
436 437 438
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
J
Johannes Berg 已提交
439
		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
440
			if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
J
Johannes Berg 已提交
441
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
442 443 444 445 446 447 448 449 450 451 452 453 454
				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 已提交
455 456 457
		*pos++ = sband->ht_cap.ampdu_factor |
			 (sband->ht_cap.ampdu_density << 2);
		memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
458 459
	}

460 461
	add_extra_ies(skb, e_ies, e_ies_len);

462 463 464 465 466 467
	kfree(ifsta->assocreq_ies);
	ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
	ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
	if (ifsta->assocreq_ies)
		memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);

J
Johannes Berg 已提交
468
	ieee80211_tx_skb(sdata, skb, 0);
469 470 471
}


472 473
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
					   u16 stype, u16 reason)
474 475
{
	struct ieee80211_local *local = sdata->local;
476
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
477 478
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
479 480
	u8 *ies;
	size_t ies_len;
481

482 483 484 485 486 487 488 489 490 491
	if (stype == IEEE80211_STYPE_DEAUTH) {
		ies = sdata->u.sta.ie_deauth;
		ies_len = sdata->u.sta.ie_deauth_len;
	} else {
		ies = sdata->u.sta.ie_disassoc;
		ies_len = sdata->u.sta.ie_disassoc_len;
	}

	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) +
			    ies_len);
492
	if (!skb) {
493 494
		printk(KERN_DEBUG "%s: failed to allocate buffer for "
		       "deauth/disassoc frame\n", sdata->dev->name);
495 496 497 498 499 500 501 502 503
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
504
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
505
	skb_put(skb, 2);
506
	/* u.deauth.reason_code == u.disassoc.reason_code */
507 508
	mgmt->u.deauth.reason_code = cpu_to_le16(reason);

509 510
	add_extra_ies(skb, ies, ies_len);

511
	ieee80211_tx_skb(sdata, skb, ifsta->flags & IEEE80211_STA_MFP_ENABLED);
512 513
}

J
Johannes Berg 已提交
514
/* MLME */
515
static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
516
					 struct ieee80211_bss *bss)
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
{
	struct ieee80211_local *local = sdata->local;
	int i, have_higher_than_11mbit = 0;

	/* cf. IEEE 802.11 9.2.12 */
	for (i = 0; i < bss->supp_rates_len; i++)
		if ((bss->supp_rates[i] & 0x7f) * 5 > 110)
			have_higher_than_11mbit = 1;

	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;

532
	ieee80211_set_wmm_default(sdata);
533 534
}

535
static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
536 537 538 539 540 541 542 543
				     struct ieee80211_if_sta *ifsta,
				     u8 *wmm_param, size_t wmm_param_len)
{
	struct ieee80211_tx_queue_params params;
	size_t left;
	int count;
	u8 *pos;

544 545 546 547 548 549
	if (!(ifsta->flags & IEEE80211_STA_WMM_ENABLED))
		return;

	if (!wmm_param)
		return;

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
		return;
	count = wmm_param[6] & 0x0f;
	if (count == ifsta->wmm_last_param_set)
		return;
	ifsta->wmm_last_param_set = count;

	pos = wmm_param + 8;
	left = wmm_param_len - 8;

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

	if (!local->ops->conf_tx)
		return;

	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) {
		case 1:
J
Johannes Berg 已提交
573
			queue = 3;
J
Johannes Berg 已提交
574
			if (acm)
575 576 577
				local->wmm_acm |= BIT(0) | BIT(3);
			break;
		case 2:
J
Johannes Berg 已提交
578
			queue = 1;
J
Johannes Berg 已提交
579
			if (acm)
580 581 582
				local->wmm_acm |= BIT(4) | BIT(5);
			break;
		case 3:
J
Johannes Berg 已提交
583
			queue = 0;
J
Johannes Berg 已提交
584
			if (acm)
585 586 587 588
				local->wmm_acm |= BIT(6) | BIT(7);
			break;
		case 0:
		default:
J
Johannes Berg 已提交
589
			queue = 2;
J
Johannes Berg 已提交
590
			if (acm)
591 592 593 594 595 596 597
				local->wmm_acm |= BIT(1) | BIT(2);
			break;
		}

		params.aifs = pos[0] & 0x0f;
		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params.cw_min = ecw2cw(pos[1] & 0x0f);
598
		params.txop = get_unaligned_le16(pos + 2);
599
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
600
		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
601
		       "cWmin=%d cWmax=%d txop=%d\n",
602
		       local->mdev->name, queue, aci, acm, params.aifs, params.cw_min,
603 604
		       params.cw_max, params.txop);
#endif
605 606 607 608
		/* TODO: handle ACM (block TX, fallback to next lowest allowed
		 * AC for now) */
		if (local->ops->conf_tx(local_to_hw(local), queue, &params)) {
			printk(KERN_DEBUG "%s: failed to set TX queue "
609
			       "parameters for queue %d\n", local->mdev->name, queue);
610 611 612 613
		}
	}
}

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
static bool check_tim(struct ieee802_11_elems *elems, u16 aid, bool *is_mc)
{
	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);

	if (tim->bitmap_ctrl & 0x01)
		*is_mc = true;

	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 已提交
638 639
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
640
{
J
Johannes Berg 已提交
641
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
642
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
643
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
644
#endif
645
	u32 changed = 0;
J
Johannes Berg 已提交
646 647 648 649 650 651 652 653 654 655 656 657 658
	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);
659

660
	if (use_protection != bss_conf->use_cts_prot) {
661
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
662
		if (net_ratelimit()) {
663
			printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n",
664
			       sdata->dev->name,
665
			       use_protection ? "enabled" : "disabled",
666
			       ifsta->bssid);
667
		}
668
#endif
669 670
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
671
	}
672

673
	if (use_short_preamble != bss_conf->use_short_preamble) {
674
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
675 676
		if (net_ratelimit()) {
			printk(KERN_DEBUG "%s: switched to %s barker preamble"
677
			       " (BSSID=%pM)\n",
678
			       sdata->dev->name,
679
			       use_short_preamble ? "short" : "long",
680
			       ifsta->bssid);
681
		}
682
#endif
683
		bss_conf->use_short_preamble = use_short_preamble;
684
		changed |= BSS_CHANGED_ERP_PREAMBLE;
685
	}
686

J
Johannes Berg 已提交
687 688 689
	if (use_short_slot != bss_conf->use_short_slot) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
		if (net_ratelimit()) {
690 691
			printk(KERN_DEBUG "%s: switched to %s slot time"
			       " (BSSID=%pM)\n",
J
Johannes Berg 已提交
692 693 694 695 696 697 698
			       sdata->dev->name,
			       use_short_slot ? "short" : "long",
			       ifsta->bssid);
		}
#endif
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
699 700 701 702 703
	}

	return changed;
}

704 705 706 707 708 709 710 711 712 713 714
static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata,
					struct ieee80211_if_sta *ifsta)
{
	union iwreq_data wrqu;
	memset(&wrqu, 0, sizeof(wrqu));
	if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
		memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
	wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
}

715
static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata,
716 717
					 struct ieee80211_if_sta *ifsta)
{
718 719 720
	char *buf;
	size_t len;
	int i;
721 722
	union iwreq_data wrqu;

723 724 725 726 727 728 729 730 731
	if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
		return;

	buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
				ifsta->assocresp_ies_len), GFP_KERNEL);
	if (!buf)
		return;

	len = sprintf(buf, "ASSOCINFO(");
732
	if (ifsta->assocreq_ies) {
733 734 735 736 737
		len += sprintf(buf + len, "ReqIEs=");
		for (i = 0; i < ifsta->assocreq_ies_len; i++) {
			len += sprintf(buf + len, "%02x",
				       ifsta->assocreq_ies[i]);
		}
738
	}
739
	if (ifsta->assocresp_ies) {
740 741 742 743 744 745 746
		if (ifsta->assocreq_ies)
			len += sprintf(buf + len, " ");
		len += sprintf(buf + len, "RespIEs=");
		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
			len += sprintf(buf + len, "%02x",
				       ifsta->assocresp_ies[i]);
		}
747
	}
748 749 750 751 752 753 754 755 756 757
	len += sprintf(buf + len, ")");

	if (len > IW_CUSTOM_MAX) {
		len = sprintf(buf, "ASSOCRESPIE=");
		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
			len += sprintf(buf + len, "%02x",
				       ifsta->assocresp_ies[i]);
		}
	}

758 759 760 761 762
	if (len <= IW_CUSTOM_MAX) {
		memset(&wrqu, 0, sizeof(wrqu));
		wrqu.data.length = len;
		wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
	}
763 764

	kfree(buf);
765 766 767
}


768
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
J
Johannes Berg 已提交
769 770
				     struct ieee80211_if_sta *ifsta,
				     u32 bss_info_changed)
771
{
772
	struct ieee80211_local *local = sdata->local;
T
Tomas Winkler 已提交
773
	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
774

775
	struct ieee80211_bss *bss;
776

J
Johannes Berg 已提交
777
	bss_info_changed |= BSS_CHANGED_ASSOC;
778
	ifsta->flags |= IEEE80211_STA_ASSOCIATED;
779

780
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
781
		return;
782

783 784 785 786 787
	bss = ieee80211_rx_bss_get(local, ifsta->bssid,
				   conf->channel->center_freq,
				   ifsta->ssid, ifsta->ssid_len);
	if (bss) {
		/* set timing information */
J
Johannes Berg 已提交
788 789 790
		sdata->vif.bss_conf.beacon_int = bss->beacon_int;
		sdata->vif.bss_conf.timestamp = bss->timestamp;
		sdata->vif.bss_conf.dtim_period = bss->dtim_period;
791

J
Johannes Berg 已提交
792
		bss_info_changed |= ieee80211_handle_bss_capability(sdata,
J
Johannes Berg 已提交
793
			bss->capability, bss->has_erp_value, bss->erp_value);
794 795

		ieee80211_rx_bss_put(local, bss);
796 797
	}

798 799 800
	ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
	memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
	ieee80211_sta_send_associnfo(sdata, ifsta);
801

802 803
	ifsta->last_probe = jiffies;
	ieee80211_led_assoc(local, 1);
804

J
Johannes Berg 已提交
805
	sdata->vif.bss_conf.assoc = 1;
806 807 808 809 810
	/*
	 * 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 已提交
811 812
	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
813

814 815 816
	if (local->powersave) {
		if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) &&
		    local->hw.conf.dynamic_ps_timeout > 0) {
817
			mod_timer(&local->dynamic_ps_timer, jiffies +
818 819
				  msecs_to_jiffies(
					local->hw.conf.dynamic_ps_timeout));
820 821 822
		} else {
			if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
				ieee80211_send_nullfunc(local, sdata, 1);
823
			conf->flags |= IEEE80211_CONF_PS;
824
			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
825
		}
826 827
	}

828 829
	netif_tx_start_all_queues(sdata->dev);
	netif_carrier_on(sdata->dev);
830

831
	ieee80211_sta_send_apinfo(sdata, ifsta);
832 833
}

834 835
static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_if_sta *ifsta)
836
{
837 838
	ifsta->direct_probe_tries++;
	if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
839 840
		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
		       sdata->dev->name, ifsta->bssid);
841
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
842
		ieee80211_sta_send_apinfo(sdata, ifsta);
843 844 845
		return;
	}

846 847
	printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n",
			sdata->dev->name, ifsta->bssid,
848
			ifsta->direct_probe_tries);
849

850
	ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
851

852 853 854 855 856 857 858 859 860
	set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request);

	/* 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,
				 ifsta->ssid, ifsta->ssid_len);

	mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
J
Johannes Berg 已提交
861
}
862

863 864 865

static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_if_sta *ifsta)
866
{
867 868
	ifsta->auth_tries++;
	if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
869
		printk(KERN_DEBUG "%s: authentication with AP %pM"
870
		       " timed out\n",
871
		       sdata->dev->name, ifsta->bssid);
872
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
873
		ieee80211_sta_send_apinfo(sdata, ifsta);
874 875 876
		return;
	}

877
	ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
878 879
	printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
	       sdata->dev->name, ifsta->bssid);
880

881 882 883
	ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0);

	mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
884 885
}

886 887 888 889
/*
 * The disassoc 'reason' argument can be either our own reason
 * if self disconnected or a reason code from the AP.
 */
890 891 892 893 894 895
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_if_sta *ifsta, bool deauth,
				   bool self_disconnected, u16 reason)
{
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
896
	u32 changed = 0, config_changed = 0;
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912

	rcu_read_lock();

	sta = sta_info_get(local, ifsta->bssid);
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	if (deauth) {
		ifsta->direct_probe_tries = 0;
		ifsta->auth_tries = 0;
	}
	ifsta->assoc_scan_tries = 0;
	ifsta->assoc_tries = 0;

913
	netif_tx_stop_all_queues(sdata->dev);
914 915
	netif_carrier_off(sdata->dev);

916
	ieee80211_sta_tear_down_BA_sessions(sdata, sta->sta.addr);
917 918 919

	if (self_disconnected) {
		if (deauth)
920 921
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DEAUTH, reason);
922
		else
923 924
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DISASSOC, reason);
925 926
	}

927 928 929 930
	ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
	changed |= ieee80211_reset_erp_info(sdata);

	ieee80211_led_assoc(local, 0);
J
Johannes Berg 已提交
931 932
	changed |= BSS_CHANGED_ASSOC;
	sdata->vif.bss_conf.assoc = false;
933 934

	ieee80211_sta_send_apinfo(sdata, ifsta);
935

936
	if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT)
937 938 939 940
		ifsta->state = IEEE80211_STA_MLME_DISABLED;

	rcu_read_unlock();

941
	/* channel(_type) changes are handled by ieee80211_hw_config */
S
Sujith 已提交
942
	local->oper_channel_type = NL80211_CHAN_NO_HT;
943

944 945
	local->power_constr_level = 0;

946 947 948
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

949 950 951 952
	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		config_changed |= IEEE80211_CONF_CHANGE_PS;
	}
J
Johannes Berg 已提交
953

954
	ieee80211_hw_config(local, config_changed);
J
Johannes Berg 已提交
955
	ieee80211_bss_info_change_notify(sdata, changed);
956 957 958 959 960 961 962 963 964 965 966 967 968 969

	rcu_read_lock();

	sta = sta_info_get(local, ifsta->bssid);
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	sta_info_unlink(&sta);

	rcu_read_unlock();

	sta_info_destroy(sta);
970
}
971

972 973 974 975 976 977 978 979
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;
}

980
static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata,
981 982
				      struct ieee80211_if_sta *ifsta)
{
983
	struct ieee80211_local *local = sdata->local;
984
	struct ieee80211_bss *bss;
985 986 987
	int bss_privacy;
	int wep_privacy;
	int privacy_invoked;
988

989
	if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
990 991
		return 0;

992
	bss = ieee80211_rx_bss_get(local, ifsta->bssid,
993
				   local->hw.conf.channel->center_freq,
994
				   ifsta->ssid, ifsta->ssid_len);
995 996 997
	if (!bss)
		return 0;

998
	bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
999
	wep_privacy = !!ieee80211_sta_wep_configured(sdata);
1000
	privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
1001

1002
	ieee80211_rx_bss_put(local, bss);
1003

1004 1005 1006 1007
	if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
		return 0;

	return 1;
1008 1009
}

1010
static void ieee80211_associate(struct ieee80211_sub_if_data *sdata,
1011 1012 1013 1014
				struct ieee80211_if_sta *ifsta)
{
	ifsta->assoc_tries++;
	if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
1015
		printk(KERN_DEBUG "%s: association with AP %pM"
1016
		       " timed out\n",
1017
		       sdata->dev->name, ifsta->bssid);
1018
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
1019
		ieee80211_sta_send_apinfo(sdata, ifsta);
1020 1021 1022
		return;
	}

1023
	ifsta->state = IEEE80211_STA_MLME_ASSOCIATE;
1024 1025
	printk(KERN_DEBUG "%s: associate with AP %pM\n",
	       sdata->dev->name, ifsta->bssid);
1026
	if (ieee80211_privacy_mismatch(sdata, ifsta)) {
1027
		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
1028
		       "mixed-cell disabled - abort association\n", sdata->dev->name);
1029
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
1030 1031 1032
		return;
	}

1033
	ieee80211_send_assoc(sdata, ifsta);
1034 1035 1036 1037 1038

	mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
}


1039
static void ieee80211_associated(struct ieee80211_sub_if_data *sdata,
1040 1041
				 struct ieee80211_if_sta *ifsta)
{
1042
	struct ieee80211_local *local = sdata->local;
1043 1044
	struct sta_info *sta;
	int disassoc;
1045
	bool remove_bss = false;
1046 1047 1048 1049 1050 1051

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

1052
	ifsta->state = IEEE80211_STA_MLME_ASSOCIATED;
1053

1054 1055
	rcu_read_lock();

1056 1057
	sta = sta_info_get(local, ifsta->bssid);
	if (!sta) {
1058 1059
		printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
		       sdata->dev->name, ifsta->bssid);
1060 1061 1062 1063 1064
		disassoc = 1;
	} else {
		disassoc = 0;
		if (time_after(jiffies,
			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
1065
			if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
1066
				printk(KERN_DEBUG "%s: No ProbeResp from "
1067
				       "current AP %pM - assume out of "
1068
				       "range\n",
1069
				       sdata->dev->name, ifsta->bssid);
1070
				disassoc = 1;
1071
				remove_bss = true;
1072
			} else
1073
				ieee80211_send_probe_req(sdata, ifsta->bssid,
1074 1075
							 ifsta->ssid,
							 ifsta->ssid_len);
1076
			ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
1077
		} else {
1078
			ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
1079 1080 1081
			if (time_after(jiffies, ifsta->last_probe +
				       IEEE80211_PROBE_INTERVAL)) {
				ifsta->last_probe = jiffies;
1082
				ieee80211_send_probe_req(sdata, ifsta->bssid,
1083 1084 1085 1086 1087
							 ifsta->ssid,
							 ifsta->ssid_len);
			}
		}
	}
1088 1089 1090

	rcu_read_unlock();

1091
	if (disassoc) {
J
Johannes Berg 已提交
1092 1093
		ieee80211_set_disassoc(sdata, ifsta, true, true,
					WLAN_REASON_PREV_AUTH_NOT_VALID);
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
		if (remove_bss) {
			struct ieee80211_bss *bss;

			bss = ieee80211_rx_bss_get(local, ifsta->bssid,
					local->hw.conf.channel->center_freq,
					ifsta->ssid, ifsta->ssid_len);
			if (bss) {
				atomic_dec(&bss->users);
				ieee80211_rx_bss_put(local, bss);
			}
		}
	} else {
J
Johannes Berg 已提交
1106 1107
		mod_timer(&ifsta->timer, jiffies +
				      IEEE80211_MONITORING_INTERVAL);
1108
	}
1109 1110 1111
}


1112
static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
1113 1114
				     struct ieee80211_if_sta *ifsta)
{
1115
	printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
1116
	ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
1117
	ieee80211_associate(sdata, ifsta);
1118 1119 1120
}


1121
static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1122 1123 1124 1125 1126 1127 1128 1129
				     struct ieee80211_if_sta *ifsta,
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u8 *pos;
	struct ieee802_11_elems elems;

	pos = mgmt->u.auth.variable;
1130
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1131
	if (!elems.challenge)
1132
		return;
1133
	ieee80211_send_auth(sdata, ifsta, 3, elems.challenge - 2,
1134 1135 1136
			    elems.challenge_len + 2, 1);
}

1137
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1138 1139 1140 1141 1142 1143
				   struct ieee80211_if_sta *ifsta,
				   struct ieee80211_mgmt *mgmt,
				   size_t len)
{
	u16 auth_alg, auth_transaction, status_code;

1144
	if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
1145
	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
1146 1147
		return;

1148
	if (len < 24 + 6)
1149 1150
		return;

1151
	if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1152
	    memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
1153 1154
		return;

1155
	if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1156
	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
1157 1158 1159 1160 1161 1162
		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);

1163
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
J
Johannes Berg 已提交
1164 1165
		/*
		 * IEEE 802.11 standard does not require authentication in IBSS
1166 1167 1168
		 * networks and most implementations do not seem to use it.
		 * However, try to reply to authentication attempts if someone
		 * has actually implemented this.
J
Johannes Berg 已提交
1169
		 */
1170
		if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
1171
			return;
1172
		ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0);
1173 1174 1175
	}

	if (auth_alg != ifsta->auth_alg ||
1176
	    auth_transaction != ifsta->auth_transaction)
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
		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;
			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
				algs[0] = WLAN_AUTH_OPEN;
			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
				algs[1] = WLAN_AUTH_SHARED_KEY;
			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
				algs[2] = WLAN_AUTH_LEAP;
			if (ifsta->auth_alg == WLAN_AUTH_OPEN)
				pos = 0;
			else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
				pos = 1;
			else
				pos = 2;
			for (i = 0; i < num_algs; i++) {
				pos++;
				if (pos >= num_algs)
					pos = 0;
				if (algs[pos] == ifsta->auth_alg ||
				    algs[pos] == 0xff)
					continue;
				if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
1205
				    !ieee80211_sta_wep_configured(sdata))
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
					continue;
				ifsta->auth_alg = algs[pos];
				break;
			}
		}
		return;
	}

	switch (ifsta->auth_alg) {
	case WLAN_AUTH_OPEN:
	case WLAN_AUTH_LEAP:
1217
		ieee80211_auth_completed(sdata, ifsta);
1218 1219 1220
		break;
	case WLAN_AUTH_SHARED_KEY:
		if (ifsta->auth_transaction == 4)
1221
			ieee80211_auth_completed(sdata, ifsta);
1222
		else
1223
			ieee80211_auth_challenge(sdata, ifsta, mgmt, len);
1224 1225 1226 1227 1228
		break;
	}
}


1229
static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1230 1231 1232 1233 1234 1235
				     struct ieee80211_if_sta *ifsta,
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u16 reason_code;

1236
	if (len < 24 + 2)
1237 1238
		return;

1239
	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN))
1240 1241 1242 1243
		return;

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

J
Johannes Berg 已提交
1244
	if (ifsta->flags & IEEE80211_STA_AUTHENTICATED)
1245 1246
		printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
				sdata->dev->name, reason_code);
1247

1248 1249 1250
	if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE ||
	    ifsta->state == IEEE80211_STA_MLME_ASSOCIATE ||
	    ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) {
1251
		ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
1252 1253 1254 1255
		mod_timer(&ifsta->timer, jiffies +
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1256
	ieee80211_set_disassoc(sdata, ifsta, true, false, 0);
1257
	ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
1258 1259 1260
}


1261
static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1262 1263 1264 1265 1266 1267
				       struct ieee80211_if_sta *ifsta,
				       struct ieee80211_mgmt *mgmt,
				       size_t len)
{
	u16 reason_code;

1268
	if (len < 24 + 2)
1269 1270
		return;

1271
	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN))
1272 1273 1274 1275
		return;

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

1276
	if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
1277 1278
		printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
				sdata->dev->name, reason_code);
1279

1280 1281
	if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) {
		ifsta->state = IEEE80211_STA_MLME_ASSOCIATE;
1282 1283 1284 1285
		mod_timer(&ifsta->timer, jiffies +
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1286
	ieee80211_set_disassoc(sdata, ifsta, false, false, reason_code);
1287 1288 1289
}


1290
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1291 1292 1293 1294 1295
					 struct ieee80211_if_sta *ifsta,
					 struct ieee80211_mgmt *mgmt,
					 size_t len,
					 int reassoc)
{
1296
	struct ieee80211_local *local = sdata->local;
1297
	struct ieee80211_supported_band *sband;
1298
	struct sta_info *sta;
1299
	u32 rates, basic_rates;
1300 1301
	u16 capab_info, status_code, aid;
	struct ieee802_11_elems elems;
J
Johannes Berg 已提交
1302
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1303
	u8 *pos;
J
Johannes Berg 已提交
1304
	u32 changed = 0;
1305
	int i, j;
1306
	bool have_higher_than_11mbit = false, newsta = false;
J
Johannes Berg 已提交
1307
	u16 ap_ht_cap_flags;
1308 1309 1310 1311

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

1312
	if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATE)
1313 1314
		return;

1315
	if (len < 24 + 6)
1316 1317
		return;

1318
	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
1319 1320 1321 1322 1323 1324
		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);

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

1330 1331 1332 1333
	pos = mgmt->u.assoc_resp.variable;
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);

	if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
1334 1335
	    elems.timeout_int && elems.timeout_int_len == 5 &&
	    elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
1336
		u32 tu, ms;
1337
		tu = get_unaligned_le32(elems.timeout_int + 1);
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
		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)
			mod_timer(&ifsta->timer,
				  jiffies + msecs_to_jiffies(ms));
		return;
	}

1348 1349
	if (status_code != WLAN_STATUS_SUCCESS) {
		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
1350
		       sdata->dev->name, status_code);
1351 1352 1353
		/* 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. */
1354
		ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
1355 1356 1357
		return;
	}

1358 1359
	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
		printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
1360
		       "set\n", sdata->dev->name, aid);
1361 1362
	aid &= ~(BIT(15) | BIT(14));

1363 1364
	if (!elems.supp_rates) {
		printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
1365
		       sdata->dev->name);
1366 1367 1368
		return;
	}

1369
	printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
1370 1371 1372 1373 1374
	ifsta->aid = aid;
	ifsta->ap_capab = capab_info;

	kfree(ifsta->assocresp_ies);
	ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
1375
	ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
1376 1377 1378
	if (ifsta->assocresp_ies)
		memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);

1379 1380
	rcu_read_lock();

1381 1382 1383
	/* Add STA entry for the AP */
	sta = sta_info_get(local, ifsta->bssid);
	if (!sta) {
1384
		struct ieee80211_bss *bss;
1385 1386

		newsta = true;
1387

J
Johannes Berg 已提交
1388 1389 1390
		sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
		if (!sta) {
			printk(KERN_DEBUG "%s: failed to alloc STA entry for"
1391
			       " the AP\n", sdata->dev->name);
1392
			rcu_read_unlock();
1393 1394
			return;
		}
J
Johannes Berg 已提交
1395 1396 1397 1398 1399 1400 1401 1402 1403
		bss = ieee80211_rx_bss_get(local, ifsta->bssid,
					   local->hw.conf.channel->center_freq,
					   ifsta->ssid, ifsta->ssid_len);
		if (bss) {
			sta->last_signal = bss->signal;
			sta->last_qual = bss->qual;
			sta->last_noise = bss->noise;
			ieee80211_rx_bss_put(local, bss);
		}
1404

J
Johannes Berg 已提交
1405 1406
		/* update new sta with its last rx activity */
		sta->last_rx = jiffies;
1407 1408
	}

J
Johannes Berg 已提交
1409 1410 1411 1412 1413 1414 1415 1416 1417
	/*
	 * 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.
	 */
1418

J
Johannes Berg 已提交
1419 1420
	set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
			   WLAN_STA_AUTHORIZED);
1421

J
Johannes Berg 已提交
1422 1423 1424
	rates = 0;
	basic_rates = 0;
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1425

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

J
Johannes Berg 已提交
1430 1431 1432 1433
		if (rate > 110)
			have_higher_than_11mbit = true;

		for (j = 0; j < sband->n_bitrates; j++) {
1434
			if (sband->bitrates[j].bitrate == rate) {
J
Johannes Berg 已提交
1435
				rates |= BIT(j);
1436 1437 1438 1439
				if (is_basic)
					basic_rates |= BIT(j);
				break;
			}
1440 1441 1442
		}
	}

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

J
Johannes Berg 已提交
1447 1448
		if (rate > 110)
			have_higher_than_11mbit = true;
1449

J
Johannes Berg 已提交
1450
		for (j = 0; j < sband->n_bitrates; j++) {
1451
			if (sband->bitrates[j].bitrate == rate) {
J
Johannes Berg 已提交
1452
				rates |= BIT(j);
1453 1454 1455 1456
				if (is_basic)
					basic_rates |= BIT(j);
				break;
			}
J
Johannes Berg 已提交
1457
		}
1458
	}
1459

J
Johannes Berg 已提交
1460
	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
J
Johannes Berg 已提交
1461
	sdata->vif.bss_conf.basic_rates = basic_rates;
J
Johannes Berg 已提交
1462 1463 1464 1465 1466 1467 1468

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

J
Johannes Berg 已提交
1470 1471
	if (elems.ht_cap_elem)
		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
J
Johannes Berg 已提交
1472
				elems.ht_cap_elem, &sta->sta.ht_cap);
J
Johannes Berg 已提交
1473 1474

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

1476
	rate_control_rate_init(sta);
1477

1478 1479 1480
	if (ifsta->flags & IEEE80211_STA_MFP_ENABLED)
		set_sta_flags(sta, WLAN_STA_MFP);

1481
	if (elems.wmm_param)
J
Johannes Berg 已提交
1482
		set_sta_flags(sta, WLAN_STA_WME);
1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496

	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)
J
Johannes Berg 已提交
1497 1498
		ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
					 elems.wmm_param_len);
1499

J
Johannes Berg 已提交
1500 1501 1502 1503 1504
	if (elems.ht_info_elem && elems.wmm_param &&
	    (ifsta->flags & IEEE80211_STA_WMM_ENABLED))
		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
					       ap_ht_cap_flags);

J
Johannes Berg 已提交
1505 1506 1507 1508
	/* set AID and assoc capability,
	 * ieee80211_set_associated() will tell the driver */
	bss_conf->aid = aid;
	bss_conf->assoc_capability = capab_info;
J
Johannes Berg 已提交
1509
	ieee80211_set_associated(sdata, ifsta, changed);
1510

J
Johannes Berg 已提交
1511
	ieee80211_associated(sdata, ifsta);
1512 1513 1514
}


1515
static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
1516
				   struct ieee80211_if_sta *ifsta,
1517
				   struct ieee80211_bss *bss)
1518
{
1519
	struct ieee80211_local *local = sdata->local;
A
Alina Friedrichsen 已提交
1520
	int res = 0, rates, i, j;
1521 1522 1523 1524
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
	u8 *pos;
	struct ieee80211_supported_band *sband;
1525
	union iwreq_data wrqu;
1526

A
Alina Friedrichsen 已提交
1527 1528 1529 1530 1531 1532 1533 1534 1535
	if (local->ops->reset_tsf) {
		/* Reset own TSF to allow time synchronization work. */
		local->ops->reset_tsf(local_to_hw(local));
	}

	if ((ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) &&
	   memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) == 0)
		return res;

1536 1537
	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +
			    sdata->u.sta.ie_proberesp_len);
1538 1539 1540 1541 1542 1543
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
		       "response\n", sdata->dev->name);
		return -ENOMEM;
	}

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

A
Alina Friedrichsen 已提交
1546 1547 1548
	if (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) {
		/* Remove possible STA entries from other IBSS networks. */
		sta_info_flush_delayed(sdata);
1549
	}
A
Alina Friedrichsen 已提交
1550

1551
	memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
1552
	res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
1553 1554 1555 1556 1557 1558 1559 1560
	if (res)
		return res;

	local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;

	sdata->drop_unencrypted = bss->capability &
		WLAN_CAPABILITY_PRIVACY ? 1 : 0;

1561
	res = ieee80211_set_freq(sdata, bss->freq);
1562

1563 1564
	if (res)
		return res;
1565

1566
	/* Build IBSS probe response */
1567

1568
	skb_reserve(skb, local->hw.extra_tx_headroom);
1569

1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
	mgmt = (struct ieee80211_mgmt *)
		skb_put(skb, 24 + sizeof(mgmt->u.beacon));
	memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						IEEE80211_STYPE_PROBE_RESP);
	memset(mgmt->da, 0xff, ETH_ALEN);
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
	mgmt->u.beacon.beacon_int =
		cpu_to_le16(local->hw.conf.beacon_int);
	mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp);
	mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
1582

1583 1584 1585 1586
	pos = skb_put(skb, 2 + ifsta->ssid_len);
	*pos++ = WLAN_EID_SSID;
	*pos++ = ifsta->ssid_len;
	memcpy(pos, ifsta->ssid, ifsta->ssid_len);
1587

1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
	rates = bss->supp_rates_len;
	if (rates > 8)
		rates = 8;
	pos = skb_put(skb, 2 + rates);
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos++ = rates;
	memcpy(pos, bss->supp_rates, rates);

	if (bss->band == IEEE80211_BAND_2GHZ) {
		pos = skb_put(skb, 2 + 1);
		*pos++ = WLAN_EID_DS_PARAMS;
		*pos++ = 1;
		*pos++ = ieee80211_frequency_to_channel(bss->freq);
	}
1602

1603 1604 1605 1606 1607 1608
	pos = skb_put(skb, 2 + 2);
	*pos++ = WLAN_EID_IBSS_PARAMS;
	*pos++ = 2;
	/* FIX: set ATIM window based on scan results */
	*pos++ = 0;
	*pos++ = 0;
1609

1610 1611 1612 1613 1614 1615
	if (bss->supp_rates_len > 8) {
		rates = bss->supp_rates_len - 8;
		pos = skb_put(skb, 2 + rates);
		*pos++ = WLAN_EID_EXT_SUPP_RATES;
		*pos++ = rates;
		memcpy(pos, &bss->supp_rates[8], rates);
1616
	}
1617

1618 1619 1620
	add_extra_ies(skb, sdata->u.sta.ie_proberesp,
		      sdata->u.sta.ie_proberesp_len);

1621 1622
	ifsta->probe_resp = skb;

1623 1624
	ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
				   IEEE80211_IFCC_BEACON_ENABLED);
1625 1626


1627 1628 1629 1630 1631 1632 1633
	rates = 0;
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
	for (i = 0; i < bss->supp_rates_len; i++) {
		int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
		for (j = 0; j < sband->n_bitrates; j++)
			if (sband->bitrates[j].bitrate == bitrate)
				rates |= BIT(j);
1634
	}
1635 1636
	ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;

1637
	ieee80211_sta_def_wmm_params(sdata, bss);
1638

1639
	ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
1640
	ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED;
1641 1642
	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);

1643 1644
	ieee80211_led_assoc(local, true);

1645 1646
	memset(&wrqu, 0, sizeof(wrqu));
	memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN);
1647
	wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
1648 1649 1650 1651

	return res;
}

1652 1653 1654 1655 1656 1657 1658 1659 1660
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;
1661
	struct ieee80211_bss *bss;
1662 1663 1664
	struct sta_info *sta;
	struct ieee80211_channel *channel;
	u64 beacon_timestamp, rx_timestamp;
1665
	u32 supp_rates = 0;
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677
	enum ieee80211_band band = rx_status->band;

	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;

1678
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates &&
1679 1680 1681 1682 1683 1684 1685
	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
		supp_rates = ieee80211_sta_get_rates(local, elems, band);

		rcu_read_lock();

		sta = sta_info_get(local, mgmt->sa);
		if (sta) {
1686
			u32 prev_rates;
1687

J
Johannes Berg 已提交
1688
			prev_rates = sta->sta.supp_rates[band];
1689
			/* make sure mandatory rates are always added */
J
Johannes Berg 已提交
1690
			sta->sta.supp_rates[band] = supp_rates |
1691
				ieee80211_mandatory_rates(local, band);
1692 1693

#ifdef CONFIG_MAC80211_IBSS_DEBUG
J
Johannes Berg 已提交
1694
			if (sta->sta.supp_rates[band] != prev_rates)
1695
				printk(KERN_DEBUG "%s: updated supp_rates set "
1696
				    "for %pM based on beacon info (0x%llx | "
1697
				    "0x%llx -> 0x%llx)\n",
1698
				    sdata->dev->name,
1699
				    sta->sta.addr,
1700 1701
				    (unsigned long long) prev_rates,
				    (unsigned long long) supp_rates,
J
Johannes Berg 已提交
1702
				    (unsigned long long) sta->sta.supp_rates[band]);
1703 1704
#endif
		} else {
R
Rami Rosen 已提交
1705
			ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
		}

		rcu_read_unlock();
	}

	bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
					freq, beacon);
	if (!bss)
		return;

S
Sujith 已提交
1716 1717 1718 1719 1720 1721 1722
	if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
	    (memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0)) {
		struct ieee80211_channel_sw_ie *sw_elem =
			(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
		ieee80211_process_chanswitch(sdata, sw_elem, bss);
	}

1723 1724 1725
	/* was just updated in ieee80211_bss_info_update */
	beacon_timestamp = bss->timestamp;

1726 1727 1728 1729
	/*
	 * In STA mode, the remaining parameters should not be overridden
	 * by beacons because they're not necessarily accurate there.
	 */
1730
	if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1731
	    bss->last_probe_resp && beacon) {
1732
		ieee80211_rx_bss_put(local, bss);
1733 1734 1735
		return;
	}

B
Bruno Randolf 已提交
1736
	/* check if we need to merge IBSS */
1737
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon &&
1738
	    (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) &&
J
Johannes Berg 已提交
1739
	    bss->capability & WLAN_CAPABILITY_IBSS &&
B
Bruno Randolf 已提交
1740
	    bss->freq == local->oper_channel->center_freq &&
1741 1742 1743
	    elems->ssid_len == sdata->u.sta.ssid_len &&
	    memcmp(elems->ssid, sdata->u.sta.ssid,
				sdata->u.sta.ssid_len) == 0) {
B
Bruno Randolf 已提交
1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
		if (rx_status->flag & RX_FLAG_TSFT) {
			/* in order for correct IBSS merging we need mactime
			 *
			 * since mactime is defined as the time the first data
			 * symbol of the frame hits the PHY, and the timestamp
			 * of the beacon is defined as "the time that the data
			 * symbol containing the first bit of the timestamp is
			 * transmitted to the PHY plus the transmitting STA’s
			 * delays through its local PHY from the MAC-PHY
			 * interface to its interface with the WM"
			 * (802.11 11.1.2) - equals the time this bit arrives at
			 * the receiver - we have to take into account the
			 * offset between the two.
			 * e.g: at 1 MBit that means mactime is 192 usec earlier
			 * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
			 */
1760 1761 1762 1763 1764
			int rate;
			if (rx_status->flag & RX_FLAG_HT) {
				rate = 65; /* TODO: HT rates */
			} else {
				rate = local->hw.wiphy->bands[band]->
B
Bruno Randolf 已提交
1765
					bitrates[rx_status->rate_idx].bitrate;
1766
			}
B
Bruno Randolf 已提交
1767 1768 1769 1770 1771 1772 1773 1774
			rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
		} else if (local && local->ops && local->ops->get_tsf)
			/* second best option: get current TSF */
			rx_timestamp = local->ops->get_tsf(local_to_hw(local));
		else
			/* can't merge without knowing the TSF */
			rx_timestamp = -1LLU;
#ifdef CONFIG_MAC80211_IBSS_DEBUG
1775 1776 1777
		printk(KERN_DEBUG "RX beacon SA=%pM BSSID="
		       "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
		       mgmt->sa, mgmt->bssid,
B
Bruno Randolf 已提交
1778 1779 1780 1781 1782 1783
		       (unsigned long long)rx_timestamp,
		       (unsigned long long)beacon_timestamp,
		       (unsigned long long)(rx_timestamp - beacon_timestamp),
		       jiffies);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
		if (beacon_timestamp > rx_timestamp) {
1784
#ifdef CONFIG_MAC80211_IBSS_DEBUG
1785
			printk(KERN_DEBUG "%s: beacon TSF higher than "
1786 1787
			       "local TSF - IBSS merge with BSSID %pM\n",
			       sdata->dev->name, mgmt->bssid);
J
Johannes Berg 已提交
1788
#endif
1789
			ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
R
Rami Rosen 已提交
1790
			ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
B
Bruno Randolf 已提交
1791 1792 1793
		}
	}

1794
	ieee80211_rx_bss_put(local, bss);
1795 1796 1797
}


1798
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1799 1800 1801 1802
					 struct ieee80211_mgmt *mgmt,
					 size_t len,
					 struct ieee80211_rx_status *rx_status)
{
1803 1804
	size_t baselen;
	struct ieee802_11_elems elems;
1805
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
1806

1807 1808 1809
	if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
		return; /* ignore ProbeResp to foreign address */

1810 1811 1812 1813 1814 1815 1816
	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);

1817
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1818 1819 1820 1821 1822 1823 1824 1825

	/* direct probe may be part of the association flow */
	if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
							&ifsta->request)) {
		printk(KERN_DEBUG "%s direct probe responded\n",
		       sdata->dev->name);
		ieee80211_authenticate(sdata, ifsta);
	}
1826 1827 1828
}


1829
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1830 1831 1832 1833 1834 1835 1836
				     struct ieee80211_mgmt *mgmt,
				     size_t len,
				     struct ieee80211_rx_status *rx_status)
{
	struct ieee80211_if_sta *ifsta;
	size_t baselen;
	struct ieee802_11_elems elems;
1837
	struct ieee80211_local *local = sdata->local;
1838
	u32 changed = 0;
1839
	bool erp_valid, directed_tim, is_mc = false;
J
Johannes Berg 已提交
1840
	u8 erp_value = 0;
1841

1842 1843 1844 1845 1846 1847 1848
	/* 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);

1849
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
1850

1851
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1852 1853 1854
		return;
	ifsta = &sdata->u.sta;

1855
	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
1856 1857 1858
	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
		return;

S
Sujith 已提交
1859 1860 1861
	if (rx_status->freq != local->hw.conf.channel->center_freq)
		return;

1862 1863 1864
	ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
				 elems.wmm_param_len);

1865 1866
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK &&
	    local->hw.conf.flags & IEEE80211_CONF_PS) {
1867 1868 1869
		directed_tim = check_tim(&elems, ifsta->aid, &is_mc);

		if (directed_tim || is_mc) {
1870 1871 1872
			local->hw.conf.flags &= ~IEEE80211_CONF_PS;
			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
			ieee80211_send_nullfunc(local, sdata, 0);
1873 1874
		}
	}
J
Johannes Berg 已提交
1875 1876 1877 1878 1879 1880

	if (elems.erp_info && elems.erp_info_len >= 1) {
		erp_valid = true;
		erp_value = elems.erp_info[0];
	} else {
		erp_valid = false;
1881
	}
J
Johannes Berg 已提交
1882 1883 1884
	changed |= ieee80211_handle_bss_capability(sdata,
			le16_to_cpu(mgmt->u.beacon.capab_info),
			erp_valid, erp_value);
1885

1886

J
Johannes Berg 已提交
1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910
	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
		struct sta_info *sta;
		struct ieee80211_supported_band *sband;
		u16 ap_ht_cap_flags;

		rcu_read_lock();

		sta = sta_info_get(local, ifsta->bssid);
		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);
1911 1912
	}

1913 1914 1915 1916 1917
	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);
1918 1919 1920 1921 1922 1923 1924

		/* 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);
1925 1926
	}

1927
	ieee80211_bss_info_change_notify(sdata, changed);
1928 1929 1930
}


1931
static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
1932 1933
					struct ieee80211_if_sta *ifsta,
					struct ieee80211_mgmt *mgmt,
1934
					size_t len)
1935
{
1936
	struct ieee80211_local *local = sdata->local;
1937 1938 1939 1940 1941
	int tx_last_beacon;
	struct sk_buff *skb;
	struct ieee80211_mgmt *resp;
	u8 *pos, *end;

1942
	if (sdata->vif.type != NL80211_IFTYPE_ADHOC ||
1943
	    ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED ||
1944 1945 1946 1947 1948 1949 1950 1951 1952
	    len < 24 + 2 || !ifsta->probe_resp)
		return;

	if (local->ops->tx_last_beacon)
		tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
	else
		tx_last_beacon = 1;

#ifdef CONFIG_MAC80211_IBSS_DEBUG
1953 1954 1955 1956
	printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM"
	       " (tx_last_beacon=%d)\n",
	       sdata->dev->name, mgmt->sa, mgmt->da,
	       mgmt->bssid, tx_last_beacon);
1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
#endif /* CONFIG_MAC80211_IBSS_DEBUG */

	if (!tx_last_beacon)
		return;

	if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
	    memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
		return;

	end = ((u8 *) mgmt) + len;
	pos = mgmt->u.probe_req.variable;
	if (pos[0] != WLAN_EID_SSID ||
	    pos + 2 + pos[1] > end) {
1970 1971
#ifdef CONFIG_MAC80211_IBSS_DEBUG
		printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
1972 1973
		       "from %pM\n",
		       sdata->dev->name, mgmt->sa);
1974
#endif
1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
		return;
	}
	if (pos[1] != 0 &&
	    (pos[1] != ifsta->ssid_len ||
	     memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
		/* Ignore ProbeReq for foreign SSID */
		return;
	}

	/* Reply with ProbeResp */
1985
	skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
1986 1987 1988 1989 1990 1991
	if (!skb)
		return;

	resp = (struct ieee80211_mgmt *) skb->data;
	memcpy(resp->da, mgmt->sa, ETH_ALEN);
#ifdef CONFIG_MAC80211_IBSS_DEBUG
1992 1993
	printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n",
	       sdata->dev->name, resp->da);
1994
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
J
Johannes Berg 已提交
1995
	ieee80211_tx_skb(sdata, skb, 0);
1996 1997
}

1998
void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
1999 2000
			   struct ieee80211_rx_status *rx_status)
{
2001
	struct ieee80211_local *local = sdata->local;
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032
	struct ieee80211_if_sta *ifsta;
	struct ieee80211_mgmt *mgmt;
	u16 fc;

	if (skb->len < 24)
		goto fail;

	ifsta = &sdata->u.sta;

	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:
		skb_queue_tail(&ifsta->skb_queue, skb);
		queue_work(local->hw.workqueue, &ifsta->work);
		return;
	}

 fail:
	kfree_skb(skb);
}

2033
static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048
					 struct sk_buff *skb)
{
	struct ieee80211_rx_status *rx_status;
	struct ieee80211_if_sta *ifsta;
	struct ieee80211_mgmt *mgmt;
	u16 fc;

	ifsta = &sdata->u.sta;

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

	switch (fc & IEEE80211_FCTL_STYPE) {
	case IEEE80211_STYPE_PROBE_REQ:
2049
		ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len);
2050 2051
		break;
	case IEEE80211_STYPE_PROBE_RESP:
2052
		ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status);
2053 2054
		break;
	case IEEE80211_STYPE_BEACON:
2055
		ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
2056 2057
		break;
	case IEEE80211_STYPE_AUTH:
2058
		ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len);
2059 2060
		break;
	case IEEE80211_STYPE_ASSOC_RESP:
2061
		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
2062 2063
		break;
	case IEEE80211_STYPE_REASSOC_RESP:
2064
		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
2065 2066
		break;
	case IEEE80211_STYPE_DEAUTH:
2067
		ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len);
2068 2069
		break;
	case IEEE80211_STYPE_DISASSOC:
2070
		ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len);
2071 2072 2073 2074 2075 2076 2077
		break;
	}

	kfree_skb(skb);
}


2078
static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
2079
{
2080
	struct ieee80211_local *local = sdata->local;
2081 2082 2083
	int active = 0;
	struct sta_info *sta;

2084 2085 2086 2087
	rcu_read_lock();

	list_for_each_entry_rcu(sta, &local->sta_list, list) {
		if (sta->sdata == sdata &&
2088 2089 2090 2091 2092 2093
		    time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
			       jiffies)) {
			active++;
			break;
		}
	}
2094 2095

	rcu_read_unlock();
2096 2097 2098 2099 2100

	return active;
}


2101
static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata,
2102 2103 2104 2105
				     struct ieee80211_if_sta *ifsta)
{
	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);

2106 2107
	ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
	if (ieee80211_sta_active_ibss(sdata))
2108 2109
		return;

2110 2111 2112 2113
	if ((sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) &&
	    (!(sdata->u.sta.flags & IEEE80211_STA_AUTO_CHANNEL_SEL)))
		return;

2114
	printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
2115
	       "IBSS networks with same SSID (merge)\n", sdata->dev->name);
2116
	ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len);
2117 2118 2119
}


J
Johannes Berg 已提交
2120
static void ieee80211_sta_timer(unsigned long data)
2121
{
J
Johannes Berg 已提交
2122 2123 2124 2125
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
	struct ieee80211_local *local = sdata->local;
2126

J
Johannes Berg 已提交
2127 2128
	set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
	queue_work(local->hw.workqueue, &ifsta->work);
2129 2130
}

2131
static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata,
2132 2133
				     struct ieee80211_if_sta *ifsta)
{
2134
	struct ieee80211_local *local = sdata->local;
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152

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

	ifsta->wmm_last_param_set = -1; /* allow any WMM update */


	if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
		ifsta->auth_alg = WLAN_AUTH_OPEN;
	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
		ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
		ifsta->auth_alg = WLAN_AUTH_LEAP;
	else
		ifsta->auth_alg = WLAN_AUTH_OPEN;
	ifsta->auth_transaction = -1;
2153
	ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
2154
	ifsta->assoc_scan_tries = 0;
2155
	ifsta->direct_probe_tries = 0;
2156 2157
	ifsta->auth_tries = 0;
	ifsta->assoc_tries = 0;
2158
	netif_tx_stop_all_queues(sdata->dev);
2159
	netif_carrier_off(sdata->dev);
2160 2161 2162 2163 2164 2165 2166 2167
}


static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
				    const char *ssid, int ssid_len)
{
	int tmp, hidden_ssid;

2168 2169
	if (ssid_len == ifsta->ssid_len &&
	    !memcmp(ifsta->ssid, ssid, ssid_len))
2170 2171
		return 1;

2172
	if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183
		return 0;

	hidden_ssid = 1;
	tmp = ssid_len;
	while (tmp--) {
		if (ssid[tmp] != '\0') {
			hidden_ssid = 0;
			break;
		}
	}

2184
	if (hidden_ssid && (ifsta->ssid_len == ssid_len || ssid_len == 0))
2185 2186 2187 2188 2189 2190 2191 2192
		return 1;

	if (ssid_len == 1 && ssid[0] == ' ')
		return 1;

	return 0;
}

2193
static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata,
2194 2195
				     struct ieee80211_if_sta *ifsta)
{
2196
	struct ieee80211_local *local = sdata->local;
2197
	struct ieee80211_bss *bss;
2198
	struct ieee80211_supported_band *sband;
2199 2200
	u8 bssid[ETH_ALEN], *pos;
	int i;
2201
	int ret;
2202

2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214
	if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) {
		memcpy(bssid, ifsta->bssid, ETH_ALEN);
	} else {
		/* Generate random, not broadcast, locally administered BSSID. Mix in
		 * own MAC address to make sure that devices that do not have proper
		 * random number generator get different BSSID. */
		get_random_bytes(bssid, ETH_ALEN);
		for (i = 0; i < ETH_ALEN; i++)
			bssid[i] ^= sdata->dev->dev_addr[i];
		bssid[0] &= ~0x01;
		bssid[0] |= 0x02;
	}
2215

2216 2217
	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n",
	       sdata->dev->name, bssid);
2218

2219
	bss = ieee80211_rx_bss_add(local, bssid,
2220
				   local->hw.conf.channel->center_freq,
2221
				   sdata->u.sta.ssid, sdata->u.sta.ssid_len);
2222 2223 2224
	if (!bss)
		return -ENOMEM;

2225 2226
	bss->band = local->hw.conf.channel->band;
	sband = local->hw.wiphy->bands[bss->band];
2227 2228

	if (local->hw.conf.beacon_int == 0)
2229
		local->hw.conf.beacon_int = 100;
2230 2231 2232
	bss->beacon_int = local->hw.conf.beacon_int;
	bss->last_update = jiffies;
	bss->capability = WLAN_CAPABILITY_IBSS;
J
Johannes Berg 已提交
2233 2234

	if (sdata->default_key)
2235
		bss->capability |= WLAN_CAPABILITY_PRIVACY;
J
Johannes Berg 已提交
2236
	else
2237
		sdata->drop_unencrypted = 0;
J
Johannes Berg 已提交
2238

2239
	bss->supp_rates_len = sband->n_bitrates;
2240
	pos = bss->supp_rates;
2241 2242
	for (i = 0; i < sband->n_bitrates; i++) {
		int rate = sband->bitrates[i].bitrate;
2243 2244 2245
		*pos++ = (u8) (rate / 5);
	}

2246
	ret = ieee80211_sta_join_ibss(sdata, ifsta, bss);
2247
	ieee80211_rx_bss_put(local, bss);
2248
	return ret;
2249 2250 2251
}


2252
static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata,
2253 2254
				   struct ieee80211_if_sta *ifsta)
{
2255
	struct ieee80211_local *local = sdata->local;
2256
	struct ieee80211_bss *bss;
2257 2258 2259 2260 2261 2262 2263
	int found = 0;
	u8 bssid[ETH_ALEN];
	int active_ibss;

	if (ifsta->ssid_len == 0)
		return -EINVAL;

2264
	active_ibss = ieee80211_sta_active_ibss(sdata);
2265 2266
#ifdef CONFIG_MAC80211_IBSS_DEBUG
	printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
2267
	       sdata->dev->name, active_ibss);
2268
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2269 2270
	spin_lock_bh(&local->bss_lock);
	list_for_each_entry(bss, &local->bss_list, list) {
2271 2272 2273 2274
		if (ifsta->ssid_len != bss->ssid_len ||
		    memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
		    || !(bss->capability & WLAN_CAPABILITY_IBSS))
			continue;
2275 2276 2277
		if ((ifsta->flags & IEEE80211_STA_BSSID_SET) &&
		    memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) != 0)
			continue;
2278
#ifdef CONFIG_MAC80211_IBSS_DEBUG
2279
		printk(KERN_DEBUG "   bssid=%pM found\n", bss->bssid);
2280 2281 2282 2283 2284 2285
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
		memcpy(bssid, bss->bssid, ETH_ALEN);
		found = 1;
		if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
			break;
	}
2286
	spin_unlock_bh(&local->bss_lock);
2287 2288

#ifdef CONFIG_MAC80211_IBSS_DEBUG
2289
	if (found)
2290 2291
		printk(KERN_DEBUG "   sta_find_ibss: selected %pM current "
		       "%pM\n", bssid, ifsta->bssid);
2292
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2293

2294 2295 2296
	if (found &&
	    ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) ||
	     memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0)) {
2297
		int ret;
2298 2299 2300 2301 2302 2303 2304
		int search_freq;

		if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
			search_freq = bss->freq;
		else
			search_freq = local->hw.conf.channel->center_freq;

2305
		bss = ieee80211_rx_bss_get(local, bssid, search_freq,
2306 2307 2308 2309
					   ifsta->ssid, ifsta->ssid_len);
		if (!bss)
			goto dont_join;

2310
		printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
2311
		       " based on configured SSID\n",
2312
		       sdata->dev->name, bssid);
2313
		ret = ieee80211_sta_join_ibss(sdata, ifsta, bss);
2314
		ieee80211_rx_bss_put(local, bss);
2315
		return ret;
2316
	}
2317 2318

dont_join:
2319 2320 2321 2322 2323
#ifdef CONFIG_MAC80211_IBSS_DEBUG
	printk(KERN_DEBUG "   did not try to join ibss\n");
#endif /* CONFIG_MAC80211_IBSS_DEBUG */

	/* Selected IBSS not found in current scan results - try to scan */
2324
	if (ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED &&
2325
	    !ieee80211_sta_active_ibss(sdata)) {
2326 2327 2328 2329 2330
		mod_timer(&ifsta->timer, jiffies +
				      IEEE80211_IBSS_MERGE_INTERVAL);
	} else if (time_after(jiffies, local->last_scan_completed +
			      IEEE80211_SCAN_INTERVAL)) {
		printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
2331
		       "join\n", sdata->dev->name);
2332
		return ieee80211_request_scan(sdata, ifsta->ssid,
2333
					      ifsta->ssid_len);
2334
	} else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) {
2335 2336 2337 2338
		int interval = IEEE80211_SCAN_INTERVAL;

		if (time_after(jiffies, ifsta->ibss_join_req +
			       IEEE80211_IBSS_JOIN_TIMEOUT)) {
2339
			if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
2340 2341
			    (!(local->oper_channel->flags &
					IEEE80211_CHAN_NO_IBSS)))
2342
				return ieee80211_sta_create_ibss(sdata, ifsta);
2343
			if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
2344
				printk(KERN_DEBUG "%s: IBSS not allowed on"
2345
				       " %d MHz\n", sdata->dev->name,
2346
				       local->hw.conf.channel->center_freq);
2347 2348 2349 2350 2351 2352 2353
			}

			/* No IBSS found - decrease scan interval and continue
			 * scanning. */
			interval = IEEE80211_SCAN_INTERVAL_SLOW;
		}

2354
		ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
2355 2356 2357 2358 2359 2360 2361 2362
		mod_timer(&ifsta->timer, jiffies + interval);
		return 0;
	}

	return 0;
}


J
Johannes Berg 已提交
2363 2364
static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_if_sta *ifsta)
2365
{
J
Johannes Berg 已提交
2366
	struct ieee80211_local *local = sdata->local;
2367
	struct ieee80211_bss *bss, *selected = NULL;
J
Johannes Berg 已提交
2368
	int top_rssi = 0, freq;
2369

2370
	spin_lock_bh(&local->bss_lock);
J
Johannes Berg 已提交
2371
	freq = local->oper_channel->center_freq;
2372
	list_for_each_entry(bss, &local->bss_list, list) {
J
Johannes Berg 已提交
2373 2374
		if (!(bss->capability & WLAN_CAPABILITY_ESS))
			continue;
2375

J
Johannes Berg 已提交
2376 2377 2378 2379 2380 2381
		if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
			IEEE80211_STA_AUTO_BSSID_SEL |
			IEEE80211_STA_AUTO_CHANNEL_SEL)) &&
		    (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
		     !!sdata->default_key))
			continue;
2382

J
Johannes Berg 已提交
2383 2384 2385
		if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
		    bss->freq != freq)
			continue;
2386

J
Johannes Berg 已提交
2387 2388 2389
		if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
		    memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
			continue;
2390

J
Johannes Berg 已提交
2391 2392 2393
		if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
		    !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
			continue;
2394

J
Johannes Berg 已提交
2395 2396 2397 2398
		if (!selected || top_rssi < bss->signal) {
			selected = bss;
			top_rssi = bss->signal;
		}
2399
	}
J
Johannes Berg 已提交
2400 2401
	if (selected)
		atomic_inc(&selected->users);
2402
	spin_unlock_bh(&local->bss_lock);
2403

J
Johannes Berg 已提交
2404 2405 2406 2407 2408 2409 2410
	if (selected) {
		ieee80211_set_freq(sdata, selected->freq);
		if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
			ieee80211_sta_set_ssid(sdata, selected->ssid,
					       selected->ssid_len);
		ieee80211_sta_set_bssid(sdata, selected->bssid);
		ieee80211_sta_def_wmm_params(sdata, selected);
2411 2412 2413 2414
		if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED)
			sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED;
		else
			sdata->u.sta.flags &= ~IEEE80211_STA_MFP_ENABLED;
2415

J
Johannes Berg 已提交
2416 2417 2418 2419 2420 2421 2422 2423 2424
		/* Send out direct probe if no probe resp was received or
		 * the one we have is outdated
		 */
		if (!selected->last_probe_resp ||
		    time_after(jiffies, selected->last_probe_resp
					+ IEEE80211_SCAN_RESULT_EXPIRE))
			ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
		else
			ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
2425

J
Johannes Berg 已提交
2426 2427 2428 2429 2430 2431 2432
		ieee80211_rx_bss_put(local, selected);
		ieee80211_sta_reset_auth(sdata, ifsta);
		return 0;
	} else {
		if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) {
			ifsta->assoc_scan_tries++;
			if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
2433
				ieee80211_start_scan(sdata, NULL, 0);
J
Johannes Berg 已提交
2434
			else
2435
				ieee80211_start_scan(sdata, ifsta->ssid,
J
Johannes Berg 已提交
2436 2437 2438
							 ifsta->ssid_len);
			ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
			set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
2439 2440
		} else {
			ifsta->assoc_scan_tries = 0;
J
Johannes Berg 已提交
2441
			ifsta->state = IEEE80211_STA_MLME_DISABLED;
2442
		}
J
Johannes Berg 已提交
2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458
	}
	return -1;
}


static void ieee80211_sta_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data, u.sta.work);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_sta *ifsta;
	struct sk_buff *skb;

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

2459
	if (local->sw_scanning || local->hw_scanning)
J
Johannes Berg 已提交
2460 2461
		return;

2462 2463
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION &&
		    sdata->vif.type != NL80211_IFTYPE_ADHOC))
J
Johannes Berg 已提交
2464
		return;
2465 2466
	ifsta = &sdata->u.sta;

J
Johannes Berg 已提交
2467 2468 2469 2470 2471 2472 2473
	while ((skb = skb_dequeue(&ifsta->skb_queue)))
		ieee80211_sta_rx_queued_mgmt(sdata, skb);

	if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE &&
	    ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
	    ifsta->state != IEEE80211_STA_MLME_ASSOCIATE &&
	    test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
2474 2475
		ieee80211_start_scan(sdata, ifsta->scan_ssid,
				     ifsta->scan_ssid_len);
J
Johannes Berg 已提交
2476
		return;
2477 2478
	}

J
Johannes Berg 已提交
2479 2480 2481 2482 2483 2484
	if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
		if (ieee80211_sta_config_auth(sdata, ifsta))
			return;
		clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
	} else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
		return;
2485

J
Johannes Berg 已提交
2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518
	switch (ifsta->state) {
	case IEEE80211_STA_MLME_DISABLED:
		break;
	case IEEE80211_STA_MLME_DIRECT_PROBE:
		ieee80211_direct_probe(sdata, ifsta);
		break;
	case IEEE80211_STA_MLME_AUTHENTICATE:
		ieee80211_authenticate(sdata, ifsta);
		break;
	case IEEE80211_STA_MLME_ASSOCIATE:
		ieee80211_associate(sdata, ifsta);
		break;
	case IEEE80211_STA_MLME_ASSOCIATED:
		ieee80211_associated(sdata, ifsta);
		break;
	case IEEE80211_STA_MLME_IBSS_SEARCH:
		ieee80211_sta_find_ibss(sdata, ifsta);
		break;
	case IEEE80211_STA_MLME_IBSS_JOINED:
		ieee80211_sta_merge_ibss(sdata, ifsta);
		break;
	default:
		WARN_ON(1);
		break;
	}

	if (ieee80211_privacy_mismatch(sdata, ifsta)) {
		printk(KERN_DEBUG "%s: privacy configuration mismatch and "
		       "mixed-cell disabled - disassociate\n", sdata->dev->name);

		ieee80211_set_disassoc(sdata, ifsta, false, true,
					WLAN_REASON_UNSPECIFIED);
	}
2519 2520
}

J
Johannes Berg 已提交
2521 2522
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
2523
	if (sdata->vif.type == NL80211_IFTYPE_STATION)
J
Johannes Berg 已提交
2524 2525 2526
		queue_work(sdata->local->hw.workqueue,
			   &sdata->u.sta.work);
}
2527

J
Johannes Berg 已提交
2528 2529
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2530
{
J
Johannes Berg 已提交
2531
	struct ieee80211_if_sta *ifsta;
J
Johannes Berg 已提交
2532

J
Johannes Berg 已提交
2533 2534
	ifsta = &sdata->u.sta;
	INIT_WORK(&ifsta->work, ieee80211_sta_work);
S
Sujith 已提交
2535
	INIT_WORK(&ifsta->chswitch_work, ieee80211_chswitch_work);
J
Johannes Berg 已提交
2536
	setup_timer(&ifsta->timer, ieee80211_sta_timer,
S
Sujith 已提交
2537 2538
		    (unsigned long) sdata);
	setup_timer(&ifsta->chswitch_timer, ieee80211_chswitch_timer,
J
Johannes Berg 已提交
2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549
		    (unsigned long) sdata);
	skb_queue_head_init(&ifsta->skb_queue);

	ifsta->capab = WLAN_CAPABILITY_ESS;
	ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
		IEEE80211_AUTH_ALG_SHARED_KEY;
	ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
		IEEE80211_STA_AUTO_BSSID_SEL |
		IEEE80211_STA_AUTO_CHANNEL_SEL;
	if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
		ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
2550 2551
}

J
Johannes Berg 已提交
2552 2553 2554 2555 2556
/*
 * Add a new IBSS station, will also be called by the RX code when,
 * in IBSS mode, receiving a frame from a yet-unknown station, hence
 * must be callable in atomic context.
 */
2557
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
2558
					u8 *bssid,u8 *addr, u32 supp_rates)
2559
{
2560
	struct ieee80211_local *local = sdata->local;
2561
	struct sta_info *sta;
2562
	int band = local->hw.conf.channel->band;
2563 2564 2565 2566 2567 2568

	/* TODO: Could consider removing the least recently used entry and
	 * allow new one to be added. */
	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
		if (net_ratelimit()) {
			printk(KERN_DEBUG "%s: No room for a new IBSS STA "
2569
			       "entry %pM\n", sdata->dev->name, addr);
2570 2571 2572 2573
		}
		return NULL;
	}

2574
	if (compare_ether_addr(bssid, sdata->u.sta.bssid))
2575 2576
		return NULL;

2577
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2578 2579
	printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n",
	       wiphy_name(local->hw.wiphy), addr, sdata->dev->name);
2580
#endif
2581

J
Johannes Berg 已提交
2582 2583
	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
	if (!sta)
2584 2585
		return NULL;

2586
	set_sta_flags(sta, WLAN_STA_AUTHORIZED);
2587

2588
	/* make sure mandatory rates are always added */
J
Johannes Berg 已提交
2589
	sta->sta.supp_rates[band] = supp_rates |
2590
			ieee80211_mandatory_rates(local, band);
2591

2592
	rate_control_rate_init(sta);
2593

2594
	if (sta_info_insert(sta))
J
Johannes Berg 已提交
2595 2596
		return NULL;

2597
	return sta;
2598 2599
}

J
Johannes Berg 已提交
2600 2601 2602
/* configuration hooks */
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
			    struct ieee80211_if_sta *ifsta)
J
Johannes Berg 已提交
2603 2604 2605
{
	struct ieee80211_local *local = sdata->local;

2606
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
J
Johannes Berg 已提交
2607
		return;
J
Johannes Berg 已提交
2608

J
Johannes Berg 已提交
2609 2610 2611 2612
	if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
			     IEEE80211_STA_AUTO_BSSID_SEL)) &&
	    (ifsta->flags & (IEEE80211_STA_SSID_SET |
			     IEEE80211_STA_AUTO_SSID_SEL))) {
J
Johannes Berg 已提交
2613

J
Johannes Berg 已提交
2614 2615 2616
		if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED)
			ieee80211_set_disassoc(sdata, ifsta, true, true,
					       WLAN_REASON_DEAUTH_LEAVING);
J
Johannes Berg 已提交
2617

J
Johannes Berg 已提交
2618 2619 2620 2621
		set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
		queue_work(local->hw.workqueue, &ifsta->work);
	}
}
J
Johannes Berg 已提交
2622

J
Johannes Berg 已提交
2623 2624 2625
int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
{
	struct ieee80211_if_sta *ifsta;
J
Johannes Berg 已提交
2626

J
Johannes Berg 已提交
2627 2628 2629 2630 2631 2632 2633 2634 2635
	if (len > IEEE80211_MAX_SSID_LEN)
		return -EINVAL;

	ifsta = &sdata->u.sta;

	if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) {
		memset(ifsta->ssid, 0, sizeof(ifsta->ssid));
		memcpy(ifsta->ssid, ssid, len);
		ifsta->ssid_len = len;
J
Johannes Berg 已提交
2636 2637
	}

2638 2639
	ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;

J
Johannes Berg 已提交
2640 2641 2642 2643
	if (len)
		ifsta->flags |= IEEE80211_STA_SSID_SET;
	else
		ifsta->flags &= ~IEEE80211_STA_SSID_SET;
J
Johannes Berg 已提交
2644

2645
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
J
Johannes Berg 已提交
2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667
		ifsta->ibss_join_req = jiffies;
		ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
		return ieee80211_sta_find_ibss(sdata, ifsta);
	}

	return 0;
}

int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
{
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
	memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
	*len = ifsta->ssid_len;
	return 0;
}

int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
{
	struct ieee80211_if_sta *ifsta;

	ifsta = &sdata->u.sta;

2668 2669 2670 2671 2672 2673 2674 2675 2676 2677
	if (is_valid_ether_addr(bssid)) {
		memcpy(ifsta->bssid, bssid, ETH_ALEN);
		ifsta->flags |= IEEE80211_STA_BSSID_SET;
	} else {
		memset(ifsta->bssid, 0, ETH_ALEN);
		ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
	}

	if (netif_running(sdata->dev)) {
		if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) {
J
Johannes Berg 已提交
2678 2679 2680 2681
			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
			       "the low-level driver\n", sdata->dev->name);
		}
	}
J
Johannes Berg 已提交
2682

2683
	return ieee80211_sta_set_ssid(sdata, ifsta->ssid, ifsta->ssid_len);
J
Johannes Berg 已提交
2684 2685 2686 2687 2688 2689 2690 2691 2692 2693
}

int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len)
{
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;

	kfree(ifsta->extra_ie);
	if (len == 0) {
		ifsta->extra_ie = NULL;
		ifsta->extra_ie_len = 0;
J
Johannes Berg 已提交
2694 2695
		return 0;
	}
J
Johannes Berg 已提交
2696 2697 2698 2699 2700 2701 2702 2703
	ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
	if (!ifsta->extra_ie) {
		ifsta->extra_ie_len = 0;
		return -ENOMEM;
	}
	memcpy(ifsta->extra_ie, ie, len);
	ifsta->extra_ie_len = len;
	return 0;
J
Johannes Berg 已提交
2704 2705
}

2706
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
2707 2708 2709
{
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;

2710
	printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
2711
	       sdata->dev->name, reason);
2712

2713 2714
	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
2715 2716
		return -EINVAL;

2717
	ieee80211_set_disassoc(sdata, ifsta, true, true, reason);
2718 2719 2720
	return 0;
}

2721
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
2722 2723 2724
{
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;

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

2728
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
2729 2730
		return -EINVAL;

2731
	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
2732 2733
		return -1;

2734
	ieee80211_set_disassoc(sdata, ifsta, false, true, reason);
2735 2736
	return 0;
}
2737

J
Johannes Berg 已提交
2738 2739 2740 2741 2742 2743
/* scan finished notification */
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
{
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
	struct ieee80211_if_sta *ifsta;

2744
	if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) {
J
Johannes Berg 已提交
2745
		ifsta = &sdata->u.sta;
2746 2747
		if ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) ||
		    !ieee80211_sta_active_ibss(sdata))
J
Johannes Berg 已提交
2748 2749 2750 2751 2752 2753 2754 2755 2756
			ieee80211_sta_find_ibss(sdata, ifsta);
	}

	/* Restart STA timers */
	rcu_read_lock();
	list_for_each_entry_rcu(sdata, &local->interfaces, list)
		ieee80211_restart_sta_timer(sdata);
	rcu_read_unlock();
}
2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777

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);
2778
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
2779 2780 2781 2782

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

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

2786
	local->hw.conf.flags |= IEEE80211_CONF_PS;
2787 2788 2789 2790 2791 2792 2793 2794 2795
	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);
}