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

14
#include <linux/delay.h>
15 16 17 18 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 846 847 848 849 850

		/*
		 * Most likely AP is not in the range so remove the
		 * bss information associated to the AP
		 */
		ieee80211_rx_bss_remove(sdata, ifsta->bssid,
				sdata->local->hw.conf.channel->center_freq,
				ifsta->ssid, ifsta->ssid_len);
851 852 853
		return;
	}

854 855
	printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n",
			sdata->dev->name, ifsta->bssid,
856
			ifsta->direct_probe_tries);
857

858
	ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
859

860 861 862 863 864 865 866 867 868
	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 已提交
869
}
870

871 872 873

static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_if_sta *ifsta)
874
{
875 876
	ifsta->auth_tries++;
	if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
877
		printk(KERN_DEBUG "%s: authentication with AP %pM"
878
		       " timed out\n",
879
		       sdata->dev->name, ifsta->bssid);
880
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
881
		ieee80211_sta_send_apinfo(sdata, ifsta);
882 883 884
		ieee80211_rx_bss_remove(sdata, ifsta->bssid,
				sdata->local->hw.conf.channel->center_freq,
				ifsta->ssid, ifsta->ssid_len);
885 886 887
		return;
	}

888
	ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
889 890
	printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
	       sdata->dev->name, ifsta->bssid);
891

892 893 894
	ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0);

	mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
895 896
}

897 898 899 900
/*
 * The disassoc 'reason' argument can be either our own reason
 * if self disconnected or a reason code from the AP.
 */
901 902 903 904 905 906
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;
907
	u32 changed = 0, config_changed = 0;
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923

	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;

924
	netif_tx_stop_all_queues(sdata->dev);
925 926
	netif_carrier_off(sdata->dev);

927
	ieee80211_sta_tear_down_BA_sessions(sdata, sta->sta.addr);
928 929 930

	if (self_disconnected) {
		if (deauth)
931 932
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DEAUTH, reason);
933
		else
934 935
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DISASSOC, reason);
936 937
	}

938 939 940 941
	ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
	changed |= ieee80211_reset_erp_info(sdata);

	ieee80211_led_assoc(local, 0);
J
Johannes Berg 已提交
942 943
	changed |= BSS_CHANGED_ASSOC;
	sdata->vif.bss_conf.assoc = false;
944 945

	ieee80211_sta_send_apinfo(sdata, ifsta);
946

947
	if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
948
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
949 950 951 952
		ieee80211_rx_bss_remove(sdata, ifsta->bssid,
				sdata->local->hw.conf.channel->center_freq,
				ifsta->ssid, ifsta->ssid_len);
	}
953 954 955

	rcu_read_unlock();

956
	/* channel(_type) changes are handled by ieee80211_hw_config */
S
Sujith 已提交
957
	local->oper_channel_type = NL80211_CHAN_NO_HT;
958

959 960
	local->power_constr_level = 0;

961 962 963
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

964 965 966 967
	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		config_changed |= IEEE80211_CONF_CHANGE_PS;
	}
J
Johannes Berg 已提交
968

969
	ieee80211_hw_config(local, config_changed);
J
Johannes Berg 已提交
970
	ieee80211_bss_info_change_notify(sdata, changed);
971 972 973 974 975 976 977 978 979 980 981 982 983 984

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

987 988 989 990 991 992 993 994
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;
}

995
static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata,
996 997
				      struct ieee80211_if_sta *ifsta)
{
998
	struct ieee80211_local *local = sdata->local;
999
	struct ieee80211_bss *bss;
1000 1001 1002
	int bss_privacy;
	int wep_privacy;
	int privacy_invoked;
1003

1004
	if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
1005 1006
		return 0;

1007
	bss = ieee80211_rx_bss_get(local, ifsta->bssid,
1008
				   local->hw.conf.channel->center_freq,
1009
				   ifsta->ssid, ifsta->ssid_len);
1010 1011 1012
	if (!bss)
		return 0;

1013
	bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
1014
	wep_privacy = !!ieee80211_sta_wep_configured(sdata);
1015
	privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
1016

1017
	ieee80211_rx_bss_put(local, bss);
1018

1019 1020 1021 1022
	if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
		return 0;

	return 1;
1023 1024
}

1025
static void ieee80211_associate(struct ieee80211_sub_if_data *sdata,
1026 1027 1028 1029
				struct ieee80211_if_sta *ifsta)
{
	ifsta->assoc_tries++;
	if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
1030
		printk(KERN_DEBUG "%s: association with AP %pM"
1031
		       " timed out\n",
1032
		       sdata->dev->name, ifsta->bssid);
1033
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
1034
		ieee80211_sta_send_apinfo(sdata, ifsta);
1035 1036 1037
		ieee80211_rx_bss_remove(sdata, ifsta->bssid,
				sdata->local->hw.conf.channel->center_freq,
				ifsta->ssid, ifsta->ssid_len);
1038 1039 1040
		return;
	}

1041
	ifsta->state = IEEE80211_STA_MLME_ASSOCIATE;
1042 1043
	printk(KERN_DEBUG "%s: associate with AP %pM\n",
	       sdata->dev->name, ifsta->bssid);
1044
	if (ieee80211_privacy_mismatch(sdata, ifsta)) {
1045
		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
1046
		       "mixed-cell disabled - abort association\n", sdata->dev->name);
1047
		ifsta->state = IEEE80211_STA_MLME_DISABLED;
1048 1049 1050
		return;
	}

1051
	ieee80211_send_assoc(sdata, ifsta);
1052 1053 1054 1055 1056

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


1057
static void ieee80211_associated(struct ieee80211_sub_if_data *sdata,
1058 1059
				 struct ieee80211_if_sta *ifsta)
{
1060
	struct ieee80211_local *local = sdata->local;
1061 1062 1063 1064 1065 1066 1067 1068
	struct sta_info *sta;
	int disassoc;

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

1069
	ifsta->state = IEEE80211_STA_MLME_ASSOCIATED;
1070

1071 1072
	rcu_read_lock();

1073 1074
	sta = sta_info_get(local, ifsta->bssid);
	if (!sta) {
1075 1076
		printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
		       sdata->dev->name, ifsta->bssid);
1077 1078 1079 1080 1081
		disassoc = 1;
	} else {
		disassoc = 0;
		if (time_after(jiffies,
			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
1082
			if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
1083
				printk(KERN_DEBUG "%s: No ProbeResp from "
1084
				       "current AP %pM - assume out of "
1085
				       "range\n",
1086
				       sdata->dev->name, ifsta->bssid);
1087
				disassoc = 1;
1088
			} else
1089
				ieee80211_send_probe_req(sdata, ifsta->bssid,
1090 1091
							 ifsta->ssid,
							 ifsta->ssid_len);
1092
			ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
1093
		} else {
1094
			ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
1095 1096 1097
			if (time_after(jiffies, ifsta->last_probe +
				       IEEE80211_PROBE_INTERVAL)) {
				ifsta->last_probe = jiffies;
1098
				ieee80211_send_probe_req(sdata, ifsta->bssid,
1099 1100 1101 1102 1103
							 ifsta->ssid,
							 ifsta->ssid_len);
			}
		}
	}
1104 1105 1106

	rcu_read_unlock();

1107
	if (disassoc)
J
Johannes Berg 已提交
1108 1109
		ieee80211_set_disassoc(sdata, ifsta, true, true,
					WLAN_REASON_PREV_AUTH_NOT_VALID);
1110
	else
J
Johannes Berg 已提交
1111 1112
		mod_timer(&ifsta->timer, jiffies +
				      IEEE80211_MONITORING_INTERVAL);
1113 1114 1115
}


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


1125
static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1126 1127 1128 1129 1130 1131 1132 1133
				     struct ieee80211_if_sta *ifsta,
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u8 *pos;
	struct ieee802_11_elems elems;

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

1141
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1142 1143 1144 1145 1146 1147
				   struct ieee80211_if_sta *ifsta,
				   struct ieee80211_mgmt *mgmt,
				   size_t len)
{
	u16 auth_alg, auth_transaction, status_code;

1148
	if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
1149
	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
1150 1151
		return;

1152
	if (len < 24 + 6)
1153 1154
		return;

1155
	if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1156
	    memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
1157 1158
		return;

1159
	if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1160
	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
1161 1162 1163 1164 1165 1166
		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);

1167
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
J
Johannes Berg 已提交
1168 1169
		/*
		 * IEEE 802.11 standard does not require authentication in IBSS
1170 1171 1172
		 * 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 已提交
1173
		 */
1174
		if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
1175
			return;
1176
		ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0);
1177 1178 1179
	}

	if (auth_alg != ifsta->auth_alg ||
1180
	    auth_transaction != ifsta->auth_transaction)
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
		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 &&
1209
				    !ieee80211_sta_wep_configured(sdata))
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
					continue;
				ifsta->auth_alg = algs[pos];
				break;
			}
		}
		return;
	}

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


1233
static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1234 1235 1236 1237 1238 1239
				     struct ieee80211_if_sta *ifsta,
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u16 reason_code;

1240
	if (len < 24 + 2)
1241 1242
		return;

1243
	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN))
1244 1245 1246 1247
		return;

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

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

1252 1253 1254
	if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE ||
	    ifsta->state == IEEE80211_STA_MLME_ASSOCIATE ||
	    ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) {
1255
		ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
1256 1257 1258 1259
		mod_timer(&ifsta->timer, jiffies +
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1260
	ieee80211_set_disassoc(sdata, ifsta, true, false, 0);
1261
	ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
1262 1263 1264
}


1265
static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1266 1267 1268 1269 1270 1271
				       struct ieee80211_if_sta *ifsta,
				       struct ieee80211_mgmt *mgmt,
				       size_t len)
{
	u16 reason_code;

1272
	if (len < 24 + 2)
1273 1274
		return;

1275
	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN))
1276 1277 1278 1279
		return;

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

1280
	if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
1281 1282
		printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
				sdata->dev->name, reason_code);
1283

1284 1285
	if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) {
		ifsta->state = IEEE80211_STA_MLME_ASSOCIATE;
1286 1287 1288 1289
		mod_timer(&ifsta->timer, jiffies +
				      IEEE80211_RETRY_AUTH_INTERVAL);
	}

1290
	ieee80211_set_disassoc(sdata, ifsta, false, false, reason_code);
1291 1292 1293
}


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

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

1316
	if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATE)
1317 1318
		return;

1319
	if (len < 24 + 6)
1320 1321
		return;

1322
	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
1323 1324 1325 1326 1327 1328
		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);

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

1334 1335 1336 1337
	pos = mgmt->u.assoc_resp.variable;
	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);

	if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
1338 1339
	    elems.timeout_int && elems.timeout_int_len == 5 &&
	    elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
1340
		u32 tu, ms;
1341
		tu = get_unaligned_le32(elems.timeout_int + 1);
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
		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;
	}

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

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

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

1373
	printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
1374 1375 1376 1377 1378
	ifsta->aid = aid;
	ifsta->ap_capab = capab_info;

	kfree(ifsta->assocresp_ies);
	ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
1379
	ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
1380 1381 1382
	if (ifsta->assocresp_ies)
		memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);

1383 1384
	rcu_read_lock();

1385 1386 1387
	/* Add STA entry for the AP */
	sta = sta_info_get(local, ifsta->bssid);
	if (!sta) {
1388
		struct ieee80211_bss *bss;
1389 1390

		newsta = true;
1391

J
Johannes Berg 已提交
1392 1393 1394
		sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
		if (!sta) {
			printk(KERN_DEBUG "%s: failed to alloc STA entry for"
1395
			       " the AP\n", sdata->dev->name);
1396
			rcu_read_unlock();
1397 1398
			return;
		}
J
Johannes Berg 已提交
1399 1400 1401 1402 1403 1404 1405 1406 1407
		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);
		}
1408

J
Johannes Berg 已提交
1409 1410
		/* update new sta with its last rx activity */
		sta->last_rx = jiffies;
1411 1412
	}

J
Johannes Berg 已提交
1413 1414 1415 1416 1417 1418 1419 1420 1421
	/*
	 * 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.
	 */
1422

J
Johannes Berg 已提交
1423 1424
	set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
			   WLAN_STA_AUTHORIZED);
1425

J
Johannes Berg 已提交
1426 1427 1428
	rates = 0;
	basic_rates = 0;
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1429

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

J
Johannes Berg 已提交
1434 1435 1436 1437
		if (rate > 110)
			have_higher_than_11mbit = true;

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

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

J
Johannes Berg 已提交
1451 1452
		if (rate > 110)
			have_higher_than_11mbit = true;
1453

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

J
Johannes Berg 已提交
1464
	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
J
Johannes Berg 已提交
1465
	sdata->vif.bss_conf.basic_rates = basic_rates;
J
Johannes Berg 已提交
1466 1467 1468 1469 1470 1471 1472

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

J
Johannes Berg 已提交
1474 1475
	if (elems.ht_cap_elem)
		ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
J
Johannes Berg 已提交
1476
				elems.ht_cap_elem, &sta->sta.ht_cap);
J
Johannes Berg 已提交
1477 1478

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

1480
	rate_control_rate_init(sta);
1481

1482 1483 1484
	if (ifsta->flags & IEEE80211_STA_MFP_ENABLED)
		set_sta_flags(sta, WLAN_STA_MFP);

1485
	if (elems.wmm_param)
J
Johannes Berg 已提交
1486
		set_sta_flags(sta, WLAN_STA_WME);
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500

	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 已提交
1501 1502
		ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
					 elems.wmm_param_len);
1503

J
Johannes Berg 已提交
1504 1505 1506 1507 1508
	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 已提交
1509 1510 1511 1512
	/* 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 已提交
1513
	ieee80211_set_associated(sdata, ifsta, changed);
1514

J
Johannes Berg 已提交
1515
	ieee80211_associated(sdata, ifsta);
1516 1517 1518
}


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

A
Alina Friedrichsen 已提交
1531 1532 1533 1534 1535 1536 1537 1538 1539
	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;

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

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

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

1555
	memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
1556
	res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
1557 1558 1559 1560 1561 1562 1563 1564
	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;

1565
	res = ieee80211_set_freq(sdata, bss->freq);
1566

1567 1568
	if (res)
		return res;
1569

1570
	/* Build IBSS probe response */
1571

1572
	skb_reserve(skb, local->hw.extra_tx_headroom);
1573

1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585
	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);
1586

1587 1588 1589 1590
	pos = skb_put(skb, 2 + ifsta->ssid_len);
	*pos++ = WLAN_EID_SSID;
	*pos++ = ifsta->ssid_len;
	memcpy(pos, ifsta->ssid, ifsta->ssid_len);
1591

1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
	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);
	}
1606

1607 1608 1609 1610 1611 1612
	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;
1613

1614 1615 1616 1617 1618 1619
	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);
1620
	}
1621

1622 1623 1624
	add_extra_ies(skb, sdata->u.sta.ie_proberesp,
		      sdata->u.sta.ie_proberesp_len);

1625 1626
	ifsta->probe_resp = skb;

1627 1628
	ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
				   IEEE80211_IFCC_BEACON_ENABLED);
1629 1630


1631 1632 1633 1634 1635 1636 1637
	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);
1638
	}
1639 1640
	ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;

1641
	ieee80211_sta_def_wmm_params(sdata, bss);
1642

1643
	ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
1644
	ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED;
1645 1646
	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);

1647 1648
	ieee80211_led_assoc(local, true);

1649 1650
	memset(&wrqu, 0, sizeof(wrqu));
	memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN);
1651
	wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
1652 1653 1654 1655

	return res;
}

1656 1657 1658 1659 1660 1661 1662 1663 1664
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;
1665
	struct ieee80211_bss *bss;
1666 1667 1668
	struct sta_info *sta;
	struct ieee80211_channel *channel;
	u64 beacon_timestamp, rx_timestamp;
1669
	u32 supp_rates = 0;
1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681
	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;

1682
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates &&
1683 1684 1685 1686 1687 1688 1689
	    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) {
1690
			u32 prev_rates;
1691

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

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

		rcu_read_unlock();
	}

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

S
Sujith 已提交
1720 1721 1722 1723 1724 1725 1726
	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);
	}

1727 1728 1729
	/* was just updated in ieee80211_bss_info_update */
	beacon_timestamp = bss->timestamp;

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

B
Bruno Randolf 已提交
1740
	/* check if we need to merge IBSS */
1741
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon &&
1742
	    (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) &&
J
Johannes Berg 已提交
1743
	    bss->capability & WLAN_CAPABILITY_IBSS &&
B
Bruno Randolf 已提交
1744
	    bss->freq == local->oper_channel->center_freq &&
1745 1746 1747
	    elems->ssid_len == sdata->u.sta.ssid_len &&
	    memcmp(elems->ssid, sdata->u.sta.ssid,
				sdata->u.sta.ssid_len) == 0) {
B
Bruno Randolf 已提交
1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
		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.
			 */
1764 1765 1766 1767 1768
			int rate;
			if (rx_status->flag & RX_FLAG_HT) {
				rate = 65; /* TODO: HT rates */
			} else {
				rate = local->hw.wiphy->bands[band]->
B
Bruno Randolf 已提交
1769
					bitrates[rx_status->rate_idx].bitrate;
1770
			}
B
Bruno Randolf 已提交
1771 1772 1773 1774 1775 1776 1777 1778
			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
1779 1780 1781
		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 已提交
1782 1783 1784 1785 1786 1787
		       (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) {
1788
#ifdef CONFIG_MAC80211_IBSS_DEBUG
1789
			printk(KERN_DEBUG "%s: beacon TSF higher than "
1790 1791
			       "local TSF - IBSS merge with BSSID %pM\n",
			       sdata->dev->name, mgmt->bssid);
J
Johannes Berg 已提交
1792
#endif
1793
			ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
R
Rami Rosen 已提交
1794
			ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
B
Bruno Randolf 已提交
1795 1796 1797
		}
	}

1798
	ieee80211_rx_bss_put(local, bss);
1799 1800 1801
}


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

1811 1812 1813
	if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
		return; /* ignore ProbeResp to foreign address */

1814 1815 1816 1817 1818 1819 1820
	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);

1821
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1822 1823 1824 1825 1826 1827 1828 1829

	/* 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);
	}
1830 1831 1832
}


1833
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1834 1835 1836 1837 1838 1839 1840
				     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;
1841
	struct ieee80211_local *local = sdata->local;
1842
	u32 changed = 0;
1843
	bool erp_valid, directed_tim, is_mc = false;
J
Johannes Berg 已提交
1844
	u8 erp_value = 0;
1845

1846 1847 1848 1849 1850 1851 1852
	/* 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);

1853
	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
1854

1855
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
1856 1857 1858
		return;
	ifsta = &sdata->u.sta;

1859
	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
1860 1861 1862
	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
		return;

S
Sujith 已提交
1863 1864 1865
	if (rx_status->freq != local->hw.conf.channel->center_freq)
		return;

1866 1867 1868
	ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
				 elems.wmm_param_len);

1869 1870
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK &&
	    local->hw.conf.flags & IEEE80211_CONF_PS) {
1871 1872 1873
		directed_tim = check_tim(&elems, ifsta->aid, &is_mc);

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

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

1890

J
Johannes Berg 已提交
1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914
	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);
1915 1916
	}

1917 1918 1919 1920 1921
	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);
1922 1923 1924 1925 1926 1927 1928

		/* 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);
1929 1930
	}

1931
	ieee80211_bss_info_change_notify(sdata, changed);
1932 1933 1934
}


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

1946
	if (sdata->vif.type != NL80211_IFTYPE_ADHOC ||
1947
	    ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED ||
1948 1949 1950 1951 1952 1953 1954 1955 1956
	    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
1957 1958 1959 1960
	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);
1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973
#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) {
1974 1975
#ifdef CONFIG_MAC80211_IBSS_DEBUG
		printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
1976 1977
		       "from %pM\n",
		       sdata->dev->name, mgmt->sa);
1978
#endif
1979 1980 1981 1982 1983 1984 1985 1986 1987 1988
		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 */
1989
	skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
1990 1991 1992 1993 1994 1995
	if (!skb)
		return;

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

2002
void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
2003 2004
			   struct ieee80211_rx_status *rx_status)
{
2005
	struct ieee80211_local *local = sdata->local;
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 2033 2034 2035 2036
	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);
}

2037
static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052
					 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:
2053
		ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len);
2054 2055
		break;
	case IEEE80211_STYPE_PROBE_RESP:
2056
		ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status);
2057 2058
		break;
	case IEEE80211_STYPE_BEACON:
2059
		ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
2060 2061
		break;
	case IEEE80211_STYPE_AUTH:
2062
		ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len);
2063 2064
		break;
	case IEEE80211_STYPE_ASSOC_RESP:
2065
		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
2066 2067
		break;
	case IEEE80211_STYPE_REASSOC_RESP:
2068
		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
2069 2070
		break;
	case IEEE80211_STYPE_DEAUTH:
2071
		ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len);
2072 2073
		break;
	case IEEE80211_STYPE_DISASSOC:
2074
		ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len);
2075 2076 2077 2078 2079 2080 2081
		break;
	}

	kfree_skb(skb);
}


2082
static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
2083
{
2084
	struct ieee80211_local *local = sdata->local;
2085 2086 2087
	int active = 0;
	struct sta_info *sta;

2088 2089 2090 2091
	rcu_read_lock();

	list_for_each_entry_rcu(sta, &local->sta_list, list) {
		if (sta->sdata == sdata &&
2092 2093 2094 2095 2096 2097
		    time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
			       jiffies)) {
			active++;
			break;
		}
	}
2098 2099

	rcu_read_unlock();
2100 2101 2102 2103 2104

	return active;
}


2105
static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata,
2106 2107 2108 2109
				     struct ieee80211_if_sta *ifsta)
{
	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);

2110 2111
	ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
	if (ieee80211_sta_active_ibss(sdata))
2112 2113
		return;

2114 2115 2116 2117
	if ((sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) &&
	    (!(sdata->u.sta.flags & IEEE80211_STA_AUTO_CHANNEL_SEL)))
		return;

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


J
Johannes Berg 已提交
2124
static void ieee80211_sta_timer(unsigned long data)
2125
{
J
Johannes Berg 已提交
2126 2127 2128 2129
	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;
2130

J
Johannes Berg 已提交
2131 2132
	set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
	queue_work(local->hw.workqueue, &ifsta->work);
2133 2134
}

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

	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;
2157
	ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
2158
	ifsta->assoc_scan_tries = 0;
2159
	ifsta->direct_probe_tries = 0;
2160 2161
	ifsta->auth_tries = 0;
	ifsta->assoc_tries = 0;
2162
	netif_tx_stop_all_queues(sdata->dev);
2163
	netif_carrier_off(sdata->dev);
2164 2165 2166 2167 2168 2169 2170 2171
}


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

2172 2173
	if (ssid_len == ifsta->ssid_len &&
	    !memcmp(ifsta->ssid, ssid, ssid_len))
2174 2175
		return 1;

2176
	if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187
		return 0;

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

2188
	if (hidden_ssid && (ifsta->ssid_len == ssid_len || ssid_len == 0))
2189 2190 2191 2192 2193 2194 2195 2196
		return 1;

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

	return 0;
}

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

2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
	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;
	}
2219

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

2223
	bss = ieee80211_rx_bss_add(local, bssid,
2224
				   local->hw.conf.channel->center_freq,
2225
				   sdata->u.sta.ssid, sdata->u.sta.ssid_len);
2226 2227 2228
	if (!bss)
		return -ENOMEM;

2229 2230
	bss->band = local->hw.conf.channel->band;
	sband = local->hw.wiphy->bands[bss->band];
2231 2232

	if (local->hw.conf.beacon_int == 0)
2233
		local->hw.conf.beacon_int = 100;
2234 2235 2236
	bss->beacon_int = local->hw.conf.beacon_int;
	bss->last_update = jiffies;
	bss->capability = WLAN_CAPABILITY_IBSS;
J
Johannes Berg 已提交
2237 2238

	if (sdata->default_key)
2239
		bss->capability |= WLAN_CAPABILITY_PRIVACY;
J
Johannes Berg 已提交
2240
	else
2241
		sdata->drop_unencrypted = 0;
J
Johannes Berg 已提交
2242

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

2250
	ret = ieee80211_sta_join_ibss(sdata, ifsta, bss);
2251
	ieee80211_rx_bss_put(local, bss);
2252
	return ret;
2253 2254 2255
}


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

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

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

#ifdef CONFIG_MAC80211_IBSS_DEBUG
2293
	if (found)
2294 2295
		printk(KERN_DEBUG "   sta_find_ibss: selected %pM current "
		       "%pM\n", bssid, ifsta->bssid);
2296
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2297

2298 2299 2300
	if (found &&
	    ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) ||
	     memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0)) {
2301
		int ret;
2302 2303 2304 2305 2306 2307 2308
		int search_freq;

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

2309
		bss = ieee80211_rx_bss_get(local, bssid, search_freq,
2310 2311 2312 2313
					   ifsta->ssid, ifsta->ssid_len);
		if (!bss)
			goto dont_join;

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

dont_join:
2323 2324 2325 2326 2327
#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 */
2328
	if (ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED &&
2329
	    !ieee80211_sta_active_ibss(sdata)) {
2330 2331 2332 2333 2334
		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 "
2335
		       "join\n", sdata->dev->name);
2336
		return ieee80211_request_scan(sdata, ifsta->ssid,
2337
					      ifsta->ssid_len);
2338
	} else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) {
2339 2340 2341 2342
		int interval = IEEE80211_SCAN_INTERVAL;

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

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

2358
		ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
2359 2360 2361 2362 2363 2364 2365 2366
		mod_timer(&ifsta->timer, jiffies + interval);
		return 0;
	}

	return 0;
}


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

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

J
Johannes Berg 已提交
2380 2381 2382 2383 2384 2385
		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;
2386

J
Johannes Berg 已提交
2387 2388 2389
		if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
		    bss->freq != freq)
			continue;
2390

J
Johannes Berg 已提交
2391 2392 2393
		if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
		    memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
			continue;
2394

J
Johannes Berg 已提交
2395 2396 2397
		if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
		    !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
			continue;
2398

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

J
Johannes Berg 已提交
2408 2409 2410 2411 2412 2413 2414
	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);
2415 2416 2417 2418
		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;
2419

J
Johannes Berg 已提交
2420 2421 2422 2423 2424 2425 2426 2427 2428
		/* 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;
2429

J
Johannes Berg 已提交
2430 2431 2432 2433 2434 2435 2436
		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)
2437
				ieee80211_start_scan(sdata, NULL, 0);
J
Johannes Berg 已提交
2438
			else
2439
				ieee80211_start_scan(sdata, ifsta->ssid,
J
Johannes Berg 已提交
2440 2441 2442
							 ifsta->ssid_len);
			ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
			set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
2443 2444
		} else {
			ifsta->assoc_scan_tries = 0;
J
Johannes Berg 已提交
2445
			ifsta->state = IEEE80211_STA_MLME_DISABLED;
2446
		}
J
Johannes Berg 已提交
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462
	}
	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;

2463
	if (local->sw_scanning || local->hw_scanning)
J
Johannes Berg 已提交
2464 2465
		return;

2466 2467
	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION &&
		    sdata->vif.type != NL80211_IFTYPE_ADHOC))
J
Johannes Berg 已提交
2468
		return;
2469 2470
	ifsta = &sdata->u.sta;

J
Johannes Berg 已提交
2471 2472 2473 2474 2475 2476 2477
	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)) {
2478 2479
		ieee80211_start_scan(sdata, ifsta->scan_ssid,
				     ifsta->scan_ssid_len);
J
Johannes Berg 已提交
2480
		return;
2481 2482
	}

J
Johannes Berg 已提交
2483 2484 2485 2486 2487 2488
	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;
2489

J
Johannes Berg 已提交
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 2519 2520 2521 2522
	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);
	}
2523 2524
}

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

J
Johannes Berg 已提交
2532 2533
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2534
{
J
Johannes Berg 已提交
2535
	struct ieee80211_if_sta *ifsta;
J
Johannes Berg 已提交
2536

J
Johannes Berg 已提交
2537 2538
	ifsta = &sdata->u.sta;
	INIT_WORK(&ifsta->work, ieee80211_sta_work);
S
Sujith 已提交
2539
	INIT_WORK(&ifsta->chswitch_work, ieee80211_chswitch_work);
J
Johannes Berg 已提交
2540
	setup_timer(&ifsta->timer, ieee80211_sta_timer,
S
Sujith 已提交
2541 2542
		    (unsigned long) sdata);
	setup_timer(&ifsta->chswitch_timer, ieee80211_chswitch_timer,
J
Johannes Berg 已提交
2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553
		    (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;
2554 2555
}

J
Johannes Berg 已提交
2556 2557 2558 2559 2560
/*
 * 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.
 */
2561
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
2562
					u8 *bssid,u8 *addr, u32 supp_rates)
2563
{
2564
	struct ieee80211_local *local = sdata->local;
2565
	struct sta_info *sta;
2566
	int band = local->hw.conf.channel->band;
2567 2568 2569 2570 2571 2572

	/* 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 "
2573
			       "entry %pM\n", sdata->dev->name, addr);
2574 2575 2576 2577
		}
		return NULL;
	}

2578
	if (compare_ether_addr(bssid, sdata->u.sta.bssid))
2579 2580
		return NULL;

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

J
Johannes Berg 已提交
2586 2587
	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
	if (!sta)
2588 2589
		return NULL;

2590
	set_sta_flags(sta, WLAN_STA_AUTHORIZED);
2591

2592
	/* make sure mandatory rates are always added */
J
Johannes Berg 已提交
2593
	sta->sta.supp_rates[band] = supp_rates |
2594
			ieee80211_mandatory_rates(local, band);
2595

2596
	rate_control_rate_init(sta);
2597

2598
	if (sta_info_insert(sta))
J
Johannes Berg 已提交
2599 2600
		return NULL;

2601
	return sta;
2602 2603
}

J
Johannes Berg 已提交
2604 2605 2606
/* configuration hooks */
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
			    struct ieee80211_if_sta *ifsta)
J
Johannes Berg 已提交
2607 2608 2609
{
	struct ieee80211_local *local = sdata->local;

2610
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
J
Johannes Berg 已提交
2611
		return;
J
Johannes Berg 已提交
2612

J
Johannes Berg 已提交
2613 2614 2615 2616
	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 已提交
2617

J
Johannes Berg 已提交
2618 2619 2620
		if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED)
			ieee80211_set_disassoc(sdata, ifsta, true, true,
					       WLAN_REASON_DEAUTH_LEAVING);
J
Johannes Berg 已提交
2621

J
Johannes Berg 已提交
2622 2623 2624 2625
		set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
		queue_work(local->hw.workqueue, &ifsta->work);
	}
}
J
Johannes Berg 已提交
2626

J
Johannes Berg 已提交
2627 2628 2629
int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
{
	struct ieee80211_if_sta *ifsta;
J
Johannes Berg 已提交
2630

J
Johannes Berg 已提交
2631 2632 2633 2634 2635 2636 2637 2638 2639
	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 已提交
2640 2641
	}

2642 2643
	ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;

J
Johannes Berg 已提交
2644 2645 2646 2647
	if (len)
		ifsta->flags |= IEEE80211_STA_SSID_SET;
	else
		ifsta->flags &= ~IEEE80211_STA_SSID_SET;
J
Johannes Berg 已提交
2648

2649
	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
J
Johannes Berg 已提交
2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671
		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;

2672 2673 2674 2675 2676 2677 2678 2679 2680 2681
	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 已提交
2682 2683 2684 2685
			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
			       "the low-level driver\n", sdata->dev->name);
		}
	}
J
Johannes Berg 已提交
2686

2687
	return ieee80211_sta_set_ssid(sdata, ifsta->ssid, ifsta->ssid_len);
J
Johannes Berg 已提交
2688 2689 2690 2691 2692 2693 2694 2695 2696 2697
}

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 已提交
2698 2699
		return 0;
	}
J
Johannes Berg 已提交
2700 2701 2702 2703 2704 2705 2706 2707
	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 已提交
2708 2709
}

2710
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
2711 2712 2713
{
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;

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

2717 2718
	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
2719 2720
		return -EINVAL;

2721
	ieee80211_set_disassoc(sdata, ifsta, true, true, reason);
2722 2723 2724
	return 0;
}

2725
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
2726 2727 2728
{
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;

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

2732
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
2733 2734
		return -EINVAL;

2735
	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
2736 2737
		return -1;

2738
	ieee80211_set_disassoc(sdata, ifsta, false, true, reason);
2739 2740
	return 0;
}
2741

J
Johannes Berg 已提交
2742 2743 2744 2745 2746 2747
/* 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;

2748
	if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) {
J
Johannes Berg 已提交
2749
		ifsta = &sdata->u.sta;
2750 2751
		if ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) ||
		    !ieee80211_sta_active_ibss(sdata))
J
Johannes Berg 已提交
2752 2753 2754 2755 2756 2757 2758 2759 2760
			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();
}
2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781

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);
2782
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
2783 2784 2785 2786

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

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

2790
	local->hw.conf.flags |= IEEE80211_CONF_PS;
2791 2792 2793 2794 2795 2796 2797 2798 2799
	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);
}