aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/Kconfig1
-rw-r--r--net/ieee80211/ieee80211_crypt.c3
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c59
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c128
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c47
-rw-r--r--net/ieee80211/ieee80211_geo.c1
-rw-r--r--net/ieee80211/ieee80211_module.c1
-rw-r--r--net/ieee80211/ieee80211_rx.c61
-rw-r--r--net/ieee80211/ieee80211_tx.c25
-rw-r--r--net/ieee80211/ieee80211_wx.c7
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c52
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c32
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c20
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c90
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_priv.h8
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c40
16 files changed, 404 insertions, 171 deletions
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
index dbb08528ddf5..f7e84e9d13ad 100644
--- a/net/ieee80211/Kconfig
+++ b/net/ieee80211/Kconfig
@@ -58,6 +58,7 @@ config IEEE80211_CRYPT_TKIP
58 depends on IEEE80211 && NET_RADIO 58 depends on IEEE80211 && NET_RADIO
59 select CRYPTO 59 select CRYPTO
60 select CRYPTO_MICHAEL_MIC 60 select CRYPTO_MICHAEL_MIC
61 select CRC32
61 ---help--- 62 ---help---
62 Include software based cipher suites in support of IEEE 802.11i 63 Include software based cipher suites in support of IEEE 802.11i
63 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled 64 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index cb71d794a7d1..5ed0a98b2d76 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -110,11 +110,10 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
110 unsigned long flags; 110 unsigned long flags;
111 struct ieee80211_crypto_alg *alg; 111 struct ieee80211_crypto_alg *alg;
112 112
113 alg = kmalloc(sizeof(*alg), GFP_KERNEL); 113 alg = kzalloc(sizeof(*alg), GFP_KERNEL);
114 if (alg == NULL) 114 if (alg == NULL)
115 return -ENOMEM; 115 return -ENOMEM;
116 116
117 memset(alg, 0, sizeof(*alg));
118 alg->ops = ops; 117 alg->ops = ops;
119 118
120 spin_lock_irqsave(&ieee80211_crypto_lock, flags); 119 spin_lock_irqsave(&ieee80211_crypto_lock, flags);
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 78b2d13e80e3..35aa3426c3fa 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -9,7 +9,7 @@
9 * more details. 9 * more details.
10 */ 10 */
11 11
12#include <linux/config.h> 12#include <linux/err.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
@@ -49,7 +49,7 @@ struct ieee80211_ccmp_data {
49 49
50 int key_idx; 50 int key_idx;
51 51
52 struct crypto_tfm *tfm; 52 struct crypto_cipher *tfm;
53 53
54 /* scratch buffers for virt_to_page() (crypto API) */ 54 /* scratch buffers for virt_to_page() (crypto API) */
55 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], 55 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
@@ -57,36 +57,26 @@ struct ieee80211_ccmp_data {
57 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; 57 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
58}; 58};
59 59
60static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, 60static inline void ieee80211_ccmp_aes_encrypt(struct crypto_cipher *tfm,
61 const u8 pt[16], u8 ct[16]) 61 const u8 pt[16], u8 ct[16])
62{ 62{
63 struct scatterlist src, dst; 63 crypto_cipher_encrypt_one(tfm, ct, pt);
64
65 src.page = virt_to_page(pt);
66 src.offset = offset_in_page(pt);
67 src.length = AES_BLOCK_LEN;
68
69 dst.page = virt_to_page(ct);
70 dst.offset = offset_in_page(ct);
71 dst.length = AES_BLOCK_LEN;
72
73 crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
74} 64}
75 65
76static void *ieee80211_ccmp_init(int key_idx) 66static void *ieee80211_ccmp_init(int key_idx)
77{ 67{
78 struct ieee80211_ccmp_data *priv; 68 struct ieee80211_ccmp_data *priv;
79 69
80 priv = kmalloc(sizeof(*priv), GFP_ATOMIC); 70 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
81 if (priv == NULL) 71 if (priv == NULL)
82 goto fail; 72 goto fail;
83 memset(priv, 0, sizeof(*priv));
84 priv->key_idx = key_idx; 73 priv->key_idx = key_idx;
85 74
86 priv->tfm = crypto_alloc_tfm("aes", 0); 75 priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
87 if (priv->tfm == NULL) { 76 if (IS_ERR(priv->tfm)) {
88 printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " 77 printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
89 "crypto API aes\n"); 78 "crypto API aes\n");
79 priv->tfm = NULL;
90 goto fail; 80 goto fail;
91 } 81 }
92 82
@@ -95,7 +85,7 @@ static void *ieee80211_ccmp_init(int key_idx)
95 fail: 85 fail:
96 if (priv) { 86 if (priv) {
97 if (priv->tfm) 87 if (priv->tfm)
98 crypto_free_tfm(priv->tfm); 88 crypto_free_cipher(priv->tfm);
99 kfree(priv); 89 kfree(priv);
100 } 90 }
101 91
@@ -106,7 +96,7 @@ static void ieee80211_ccmp_deinit(void *priv)
106{ 96{
107 struct ieee80211_ccmp_data *_priv = priv; 97 struct ieee80211_ccmp_data *_priv = priv;
108 if (_priv && _priv->tfm) 98 if (_priv && _priv->tfm)
109 crypto_free_tfm(_priv->tfm); 99 crypto_free_cipher(_priv->tfm);
110 kfree(priv); 100 kfree(priv);
111} 101}
112 102
@@ -117,7 +107,7 @@ static inline void xor_block(u8 * b, u8 * a, size_t len)
117 b[i] ^= a[i]; 107 b[i] ^= a[i];
118} 108}
119 109
120static void ccmp_init_blocks(struct crypto_tfm *tfm, 110static void ccmp_init_blocks(struct crypto_cipher *tfm,
121 struct ieee80211_hdr_4addr *hdr, 111 struct ieee80211_hdr_4addr *hdr,
122 u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) 112 u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
123{ 113{
@@ -273,6 +263,27 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
273 return 0; 263 return 0;
274} 264}
275 265
266/*
267 * deal with seq counter wrapping correctly.
268 * refer to timer_after() for jiffies wrapping handling
269 */
270static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o)
271{
272 u32 iv32_n, iv16_n;
273 u32 iv32_o, iv16_o;
274
275 iv32_n = (pn_n[0] << 24) | (pn_n[1] << 16) | (pn_n[2] << 8) | pn_n[3];
276 iv16_n = (pn_n[4] << 8) | pn_n[5];
277
278 iv32_o = (pn_o[0] << 24) | (pn_o[1] << 16) | (pn_o[2] << 8) | pn_o[3];
279 iv16_o = (pn_o[4] << 8) | pn_o[5];
280
281 if ((s32)iv32_n - (s32)iv32_o < 0 ||
282 (iv32_n == iv32_o && iv16_n <= iv16_o))
283 return 1;
284 return 0;
285}
286
276static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 287static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
277{ 288{
278 struct ieee80211_ccmp_data *key = priv; 289 struct ieee80211_ccmp_data *key = priv;
@@ -325,7 +336,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
325 pn[5] = pos[0]; 336 pn[5] = pos[0];
326 pos += 8; 337 pos += 8;
327 338
328 if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { 339 if (ccmp_replay_check(pn, key->rx_pn)) {
329 if (net_ratelimit()) { 340 if (net_ratelimit()) {
330 printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT 341 printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
331 " previous PN %02x%02x%02x%02x%02x%02x " 342 " previous PN %02x%02x%02x%02x%02x%02x "
@@ -379,7 +390,7 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
379{ 390{
380 struct ieee80211_ccmp_data *data = priv; 391 struct ieee80211_ccmp_data *data = priv;
381 int keyidx; 392 int keyidx;
382 struct crypto_tfm *tfm = data->tfm; 393 struct crypto_cipher *tfm = data->tfm;
383 394
384 keyidx = data->key_idx; 395 keyidx = data->key_idx;
385 memset(data, 0, sizeof(*data)); 396 memset(data, 0, sizeof(*data));
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 3fa5df2e1f0b..4200ec509866 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -9,7 +9,7 @@
9 * more details. 9 * more details.
10 */ 10 */
11 11
12#include <linux/config.h> 12#include <linux/err.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
@@ -53,8 +53,10 @@ struct ieee80211_tkip_data {
53 53
54 int key_idx; 54 int key_idx;
55 55
56 struct crypto_tfm *tfm_arc4; 56 struct crypto_blkcipher *rx_tfm_arc4;
57 struct crypto_tfm *tfm_michael; 57 struct crypto_hash *rx_tfm_michael;
58 struct crypto_blkcipher *tx_tfm_arc4;
59 struct crypto_hash *tx_tfm_michael;
58 60
59 /* scratch buffers for virt_to_page() (crypto API) */ 61 /* scratch buffers for virt_to_page() (crypto API) */
60 u8 rx_hdr[16], tx_hdr[16]; 62 u8 rx_hdr[16], tx_hdr[16];
@@ -86,17 +88,39 @@ static void *ieee80211_tkip_init(int key_idx)
86 88
87 priv->key_idx = key_idx; 89 priv->key_idx = key_idx;
88 90
89 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0); 91 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
90 if (priv->tfm_arc4 == NULL) { 92 CRYPTO_ALG_ASYNC);
93 if (IS_ERR(priv->tx_tfm_arc4)) {
91 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 94 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
92 "crypto API arc4\n"); 95 "crypto API arc4\n");
96 priv->tx_tfm_arc4 = NULL;
93 goto fail; 97 goto fail;
94 } 98 }
95 99
96 priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0); 100 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
97 if (priv->tfm_michael == NULL) { 101 CRYPTO_ALG_ASYNC);
102 if (IS_ERR(priv->tx_tfm_michael)) {
98 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 103 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
99 "crypto API michael_mic\n"); 104 "crypto API michael_mic\n");
105 priv->tx_tfm_michael = NULL;
106 goto fail;
107 }
108
109 priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
110 CRYPTO_ALG_ASYNC);
111 if (IS_ERR(priv->rx_tfm_arc4)) {
112 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
113 "crypto API arc4\n");
114 priv->rx_tfm_arc4 = NULL;
115 goto fail;
116 }
117
118 priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
119 CRYPTO_ALG_ASYNC);
120 if (IS_ERR(priv->rx_tfm_michael)) {
121 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
122 "crypto API michael_mic\n");
123 priv->rx_tfm_michael = NULL;
100 goto fail; 124 goto fail;
101 } 125 }
102 126
@@ -104,10 +128,14 @@ static void *ieee80211_tkip_init(int key_idx)
104 128
105 fail: 129 fail:
106 if (priv) { 130 if (priv) {
107 if (priv->tfm_michael) 131 if (priv->tx_tfm_michael)
108 crypto_free_tfm(priv->tfm_michael); 132 crypto_free_hash(priv->tx_tfm_michael);
109 if (priv->tfm_arc4) 133 if (priv->tx_tfm_arc4)
110 crypto_free_tfm(priv->tfm_arc4); 134 crypto_free_blkcipher(priv->tx_tfm_arc4);
135 if (priv->rx_tfm_michael)
136 crypto_free_hash(priv->rx_tfm_michael);
137 if (priv->rx_tfm_arc4)
138 crypto_free_blkcipher(priv->rx_tfm_arc4);
111 kfree(priv); 139 kfree(priv);
112 } 140 }
113 141
@@ -117,10 +145,16 @@ static void *ieee80211_tkip_init(int key_idx)
117static void ieee80211_tkip_deinit(void *priv) 145static void ieee80211_tkip_deinit(void *priv)
118{ 146{
119 struct ieee80211_tkip_data *_priv = priv; 147 struct ieee80211_tkip_data *_priv = priv;
120 if (_priv && _priv->tfm_michael) 148 if (_priv) {
121 crypto_free_tfm(_priv->tfm_michael); 149 if (_priv->tx_tfm_michael)
122 if (_priv && _priv->tfm_arc4) 150 crypto_free_hash(_priv->tx_tfm_michael);
123 crypto_free_tfm(_priv->tfm_arc4); 151 if (_priv->tx_tfm_arc4)
152 crypto_free_blkcipher(_priv->tx_tfm_arc4);
153 if (_priv->rx_tfm_michael)
154 crypto_free_hash(_priv->rx_tfm_michael);
155 if (_priv->rx_tfm_arc4)
156 crypto_free_blkcipher(_priv->rx_tfm_arc4);
157 }
124 kfree(priv); 158 kfree(priv);
125} 159}
126 160
@@ -319,6 +353,7 @@ static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
319static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 353static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
320{ 354{
321 struct ieee80211_tkip_data *tkey = priv; 355 struct ieee80211_tkip_data *tkey = priv;
356 struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
322 int len; 357 int len;
323 u8 rc4key[16], *pos, *icv; 358 u8 rc4key[16], *pos, *icv;
324 u32 crc; 359 u32 crc;
@@ -352,18 +387,30 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
352 icv[2] = crc >> 16; 387 icv[2] = crc >> 16;
353 icv[3] = crc >> 24; 388 icv[3] = crc >> 24;
354 389
355 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); 390 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
356 sg.page = virt_to_page(pos); 391 sg.page = virt_to_page(pos);
357 sg.offset = offset_in_page(pos); 392 sg.offset = offset_in_page(pos);
358 sg.length = len + 4; 393 sg.length = len + 4;
359 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4); 394 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
395}
360 396
397/*
398 * deal with seq counter wrapping correctly.
399 * refer to timer_after() for jiffies wrapping handling
400 */
401static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
402 u32 iv32_o, u16 iv16_o)
403{
404 if ((s32)iv32_n - (s32)iv32_o < 0 ||
405 (iv32_n == iv32_o && iv16_n <= iv16_o))
406 return 1;
361 return 0; 407 return 0;
362} 408}
363 409
364static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 410static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
365{ 411{
366 struct ieee80211_tkip_data *tkey = priv; 412 struct ieee80211_tkip_data *tkey = priv;
413 struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
367 u8 rc4key[16]; 414 u8 rc4key[16];
368 u8 keyidx, *pos; 415 u8 keyidx, *pos;
369 u32 iv32; 416 u32 iv32;
@@ -415,8 +462,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
415 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); 462 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
416 pos += 8; 463 pos += 8;
417 464
418 if (iv32 < tkey->rx_iv32 || 465 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
419 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
420 if (net_ratelimit()) { 466 if (net_ratelimit()) {
421 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT 467 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
422 " previous TSC %08x%04x received TSC " 468 " previous TSC %08x%04x received TSC "
@@ -435,11 +481,18 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
435 481
436 plen = skb->len - hdr_len - 12; 482 plen = skb->len - hdr_len - 12;
437 483
438 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); 484 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
439 sg.page = virt_to_page(pos); 485 sg.page = virt_to_page(pos);
440 sg.offset = offset_in_page(pos); 486 sg.offset = offset_in_page(pos);
441 sg.length = plen + 4; 487 sg.length = plen + 4;
442 crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4); 488 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
489 if (net_ratelimit()) {
490 printk(KERN_DEBUG ": TKIP: failed to decrypt "
491 "received packet from " MAC_FMT "\n",
492 MAC_ARG(hdr->addr2));
493 }
494 return -7;
495 }
443 496
444 crc = ~crc32_le(~0, pos, plen); 497 crc = ~crc32_le(~0, pos, plen);
445 icv[0] = crc; 498 icv[0] = crc;
@@ -473,12 +526,13 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
473 return keyidx; 526 return keyidx;
474} 527}
475 528
476static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr, 529static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
477 u8 * data, size_t data_len, u8 * mic) 530 u8 * data, size_t data_len, u8 * mic)
478{ 531{
532 struct hash_desc desc;
479 struct scatterlist sg[2]; 533 struct scatterlist sg[2];
480 534
481 if (tkey->tfm_michael == NULL) { 535 if (tfm_michael == NULL) {
482 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); 536 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
483 return -1; 537 return -1;
484 } 538 }
@@ -490,12 +544,12 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
490 sg[1].offset = offset_in_page(data); 544 sg[1].offset = offset_in_page(data);
491 sg[1].length = data_len; 545 sg[1].length = data_len;
492 546
493 crypto_digest_init(tkey->tfm_michael); 547 if (crypto_hash_setkey(tfm_michael, key, 8))
494 crypto_digest_setkey(tkey->tfm_michael, key, 8); 548 return -1;
495 crypto_digest_update(tkey->tfm_michael, sg, 2);
496 crypto_digest_final(tkey->tfm_michael, mic);
497 549
498 return 0; 550 desc.tfm = tfm_michael;
551 desc.flags = 0;
552 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
499} 553}
500 554
501static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) 555static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
@@ -529,7 +583,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
529 if (stype & IEEE80211_STYPE_QOS_DATA) { 583 if (stype & IEEE80211_STYPE_QOS_DATA) {
530 const struct ieee80211_hdr_3addrqos *qoshdr = 584 const struct ieee80211_hdr_3addrqos *qoshdr =
531 (struct ieee80211_hdr_3addrqos *)skb->data; 585 (struct ieee80211_hdr_3addrqos *)skb->data;
532 hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; 586 hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID);
533 } else 587 } else
534 hdr[12] = 0; /* priority */ 588 hdr[12] = 0; /* priority */
535 589
@@ -551,7 +605,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
551 605
552 michael_mic_hdr(skb, tkey->tx_hdr); 606 michael_mic_hdr(skb, tkey->tx_hdr);
553 pos = skb_put(skb, 8); 607 pos = skb_put(skb, 8);
554 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr, 608 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
555 skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) 609 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
556 return -1; 610 return -1;
557 611
@@ -589,7 +643,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
589 return -1; 643 return -1;
590 644
591 michael_mic_hdr(skb, tkey->rx_hdr); 645 michael_mic_hdr(skb, tkey->rx_hdr);
592 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr, 646 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
593 skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) 647 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
594 return -1; 648 return -1;
595 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { 649 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
@@ -619,14 +673,18 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
619{ 673{
620 struct ieee80211_tkip_data *tkey = priv; 674 struct ieee80211_tkip_data *tkey = priv;
621 int keyidx; 675 int keyidx;
622 struct crypto_tfm *tfm = tkey->tfm_michael; 676 struct crypto_hash *tfm = tkey->tx_tfm_michael;
623 struct crypto_tfm *tfm2 = tkey->tfm_arc4; 677 struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
678 struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
679 struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
624 680
625 keyidx = tkey->key_idx; 681 keyidx = tkey->key_idx;
626 memset(tkey, 0, sizeof(*tkey)); 682 memset(tkey, 0, sizeof(*tkey));
627 tkey->key_idx = keyidx; 683 tkey->key_idx = keyidx;
628 tkey->tfm_michael = tfm; 684 tkey->tx_tfm_michael = tfm;
629 tkey->tfm_arc4 = tfm2; 685 tkey->tx_tfm_arc4 = tfm2;
686 tkey->rx_tfm_michael = tfm3;
687 tkey->rx_tfm_arc4 = tfm4;
630 if (len == TKIP_KEY_LEN) { 688 if (len == TKIP_KEY_LEN) {
631 memcpy(tkey->key, key, TKIP_KEY_LEN); 689 memcpy(tkey->key, key, TKIP_KEY_LEN);
632 tkey->key_set = 1; 690 tkey->key_set = 1;
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 649e581fa565..1b2efff11d39 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -9,7 +9,7 @@
9 * more details. 9 * more details.
10 */ 10 */
11 11
12#include <linux/config.h> 12#include <linux/err.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
@@ -33,26 +33,34 @@ struct prism2_wep_data {
33 u8 key[WEP_KEY_LEN + 1]; 33 u8 key[WEP_KEY_LEN + 1];
34 u8 key_len; 34 u8 key_len;
35 u8 key_idx; 35 u8 key_idx;
36 struct crypto_tfm *tfm; 36 struct crypto_blkcipher *tx_tfm;
37 struct crypto_blkcipher *rx_tfm;
37}; 38};
38 39
39static void *prism2_wep_init(int keyidx) 40static void *prism2_wep_init(int keyidx)
40{ 41{
41 struct prism2_wep_data *priv; 42 struct prism2_wep_data *priv;
42 43
43 priv = kmalloc(sizeof(*priv), GFP_ATOMIC); 44 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
44 if (priv == NULL) 45 if (priv == NULL)
45 goto fail; 46 goto fail;
46 memset(priv, 0, sizeof(*priv));
47 priv->key_idx = keyidx; 47 priv->key_idx = keyidx;
48 48
49 priv->tfm = crypto_alloc_tfm("arc4", 0); 49 priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
50 if (priv->tfm == NULL) { 50 if (IS_ERR(priv->tx_tfm)) {
51 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " 51 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
52 "crypto API arc4\n"); 52 "crypto API arc4\n");
53 priv->tx_tfm = NULL;
53 goto fail; 54 goto fail;
54 } 55 }
55 56
57 priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
58 if (IS_ERR(priv->rx_tfm)) {
59 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
60 "crypto API arc4\n");
61 priv->rx_tfm = NULL;
62 goto fail;
63 }
56 /* start WEP IV from a random value */ 64 /* start WEP IV from a random value */
57 get_random_bytes(&priv->iv, 4); 65 get_random_bytes(&priv->iv, 4);
58 66
@@ -60,8 +68,10 @@ static void *prism2_wep_init(int keyidx)
60 68
61 fail: 69 fail:
62 if (priv) { 70 if (priv) {
63 if (priv->tfm) 71 if (priv->tx_tfm)
64 crypto_free_tfm(priv->tfm); 72 crypto_free_blkcipher(priv->tx_tfm);
73 if (priv->rx_tfm)
74 crypto_free_blkcipher(priv->rx_tfm);
65 kfree(priv); 75 kfree(priv);
66 } 76 }
67 return NULL; 77 return NULL;
@@ -70,8 +80,12 @@ static void *prism2_wep_init(int keyidx)
70static void prism2_wep_deinit(void *priv) 80static void prism2_wep_deinit(void *priv)
71{ 81{
72 struct prism2_wep_data *_priv = priv; 82 struct prism2_wep_data *_priv = priv;
73 if (_priv && _priv->tfm) 83 if (_priv) {
74 crypto_free_tfm(_priv->tfm); 84 if (_priv->tx_tfm)
85 crypto_free_blkcipher(_priv->tx_tfm);
86 if (_priv->rx_tfm)
87 crypto_free_blkcipher(_priv->rx_tfm);
88 }
75 kfree(priv); 89 kfree(priv);
76} 90}
77 91
@@ -122,6 +136,7 @@ static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
122static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 136static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
123{ 137{
124 struct prism2_wep_data *wep = priv; 138 struct prism2_wep_data *wep = priv;
139 struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
125 u32 crc, klen, len; 140 u32 crc, klen, len;
126 u8 *pos, *icv; 141 u8 *pos, *icv;
127 struct scatterlist sg; 142 struct scatterlist sg;
@@ -153,13 +168,11 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
153 icv[2] = crc >> 16; 168 icv[2] = crc >> 16;
154 icv[3] = crc >> 24; 169 icv[3] = crc >> 24;
155 170
156 crypto_cipher_setkey(wep->tfm, key, klen); 171 crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
157 sg.page = virt_to_page(pos); 172 sg.page = virt_to_page(pos);
158 sg.offset = offset_in_page(pos); 173 sg.offset = offset_in_page(pos);
159 sg.length = len + 4; 174 sg.length = len + 4;
160 crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4); 175 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
161
162 return 0;
163} 176}
164 177
165/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of 178/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
@@ -172,6 +185,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
172static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 185static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
173{ 186{
174 struct prism2_wep_data *wep = priv; 187 struct prism2_wep_data *wep = priv;
188 struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
175 u32 crc, klen, plen; 189 u32 crc, klen, plen;
176 u8 key[WEP_KEY_LEN + 3]; 190 u8 key[WEP_KEY_LEN + 3];
177 u8 keyidx, *pos, icv[4]; 191 u8 keyidx, *pos, icv[4];
@@ -196,11 +210,12 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
196 /* Apply RC4 to data and compute CRC32 over decrypted data */ 210 /* Apply RC4 to data and compute CRC32 over decrypted data */
197 plen = skb->len - hdr_len - 8; 211 plen = skb->len - hdr_len - 8;
198 212
199 crypto_cipher_setkey(wep->tfm, key, klen); 213 crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
200 sg.page = virt_to_page(pos); 214 sg.page = virt_to_page(pos);
201 sg.offset = offset_in_page(pos); 215 sg.offset = offset_in_page(pos);
202 sg.length = plen + 4; 216 sg.length = plen + 4;
203 crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4); 217 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
218 return -7;
204 219
205 crc = ~crc32_le(~0, pos, plen); 220 crc = ~crc32_le(~0, pos, plen);
206 icv[0] = crc; 221 icv[0] = crc;
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
index 192243ab35ed..305a09de85a5 100644
--- a/net/ieee80211/ieee80211_geo.c
+++ b/net/ieee80211/ieee80211_geo.c
@@ -24,7 +24,6 @@
24 24
25******************************************************************************/ 25******************************************************************************/
26#include <linux/compiler.h> 26#include <linux/compiler.h>
27#include <linux/config.h>
28#include <linux/errno.h> 27#include <linux/errno.h>
29#include <linux/if_arp.h> 28#include <linux/if_arp.h>
30#include <linux/in6.h> 29#include <linux/in6.h>
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 2cb84d84f671..13b1e5fff7e4 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -31,7 +31,6 @@
31*******************************************************************************/ 31*******************************************************************************/
32 32
33#include <linux/compiler.h> 33#include <linux/compiler.h>
34#include <linux/config.h>
35#include <linux/errno.h> 34#include <linux/errno.h>
36#include <linux/if_arp.h> 35#include <linux/if_arp.h>
37#include <linux/in6.h> 36#include <linux/in6.h>
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 2bf567fd5a17..770704183a1b 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -14,7 +14,6 @@
14 */ 14 */
15 15
16#include <linux/compiler.h> 16#include <linux/compiler.h>
17#include <linux/config.h>
18#include <linux/errno.h> 17#include <linux/errno.h>
19#include <linux/if_arp.h> 18#include <linux/if_arp.h>
20#include <linux/in6.h> 19#include <linux/in6.h>
@@ -369,6 +368,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
369 368
370 /* Put this code here so that we avoid duplicating it in all 369 /* Put this code here so that we avoid duplicating it in all
371 * Rx paths. - Jean II */ 370 * Rx paths. - Jean II */
371#ifdef CONFIG_WIRELESS_EXT
372#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ 372#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
373 /* If spy monitoring on */ 373 /* If spy monitoring on */
374 if (ieee->spy_data.spy_number > 0) { 374 if (ieee->spy_data.spy_number > 0) {
@@ -397,15 +397,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
397 wireless_spy_update(ieee->dev, hdr->addr2, &wstats); 397 wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
398 } 398 }
399#endif /* IW_WIRELESS_SPY */ 399#endif /* IW_WIRELESS_SPY */
400#endif /* CONFIG_WIRELESS_EXT */
400 401
401#ifdef NOT_YET 402#ifdef NOT_YET
402 hostap_update_rx_stats(local->ap, hdr, rx_stats); 403 hostap_update_rx_stats(local->ap, hdr, rx_stats);
403#endif 404#endif
404 405
405 if (ieee->iw_mode == IW_MODE_MONITOR) { 406 if (ieee->iw_mode == IW_MODE_MONITOR) {
406 ieee80211_monitor_rx(ieee, skb, rx_stats);
407 stats->rx_packets++; 407 stats->rx_packets++;
408 stats->rx_bytes += skb->len; 408 stats->rx_bytes += skb->len;
409 ieee80211_monitor_rx(ieee, skb, rx_stats);
409 return 1; 410 return 1;
410 } 411 }
411 412
@@ -778,33 +779,44 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
778 return 0; 779 return 0;
779} 780}
780 781
781/* Filter out unrelated packets, call ieee80211_rx[_mgt] */ 782/* Filter out unrelated packets, call ieee80211_rx[_mgt]
782int ieee80211_rx_any(struct ieee80211_device *ieee, 783 * This function takes over the skb, it should not be used again after calling
784 * this function. */
785void ieee80211_rx_any(struct ieee80211_device *ieee,
783 struct sk_buff *skb, struct ieee80211_rx_stats *stats) 786 struct sk_buff *skb, struct ieee80211_rx_stats *stats)
784{ 787{
785 struct ieee80211_hdr_4addr *hdr; 788 struct ieee80211_hdr_4addr *hdr;
786 int is_packet_for_us; 789 int is_packet_for_us;
787 u16 fc; 790 u16 fc;
788 791
789 if (ieee->iw_mode == IW_MODE_MONITOR) 792 if (ieee->iw_mode == IW_MODE_MONITOR) {
790 return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL; 793 if (!ieee80211_rx(ieee, skb, stats))
794 dev_kfree_skb_irq(skb);
795 return;
796 }
797
798 if (skb->len < sizeof(struct ieee80211_hdr))
799 goto drop_free;
791 800
792 hdr = (struct ieee80211_hdr_4addr *)skb->data; 801 hdr = (struct ieee80211_hdr_4addr *)skb->data;
793 fc = le16_to_cpu(hdr->frame_ctl); 802 fc = le16_to_cpu(hdr->frame_ctl);
794 803
795 if ((fc & IEEE80211_FCTL_VERS) != 0) 804 if ((fc & IEEE80211_FCTL_VERS) != 0)
796 return -EINVAL; 805 goto drop_free;
797 806
798 switch (fc & IEEE80211_FCTL_FTYPE) { 807 switch (fc & IEEE80211_FCTL_FTYPE) {
799 case IEEE80211_FTYPE_MGMT: 808 case IEEE80211_FTYPE_MGMT:
809 if (skb->len < sizeof(struct ieee80211_hdr_3addr))
810 goto drop_free;
800 ieee80211_rx_mgt(ieee, hdr, stats); 811 ieee80211_rx_mgt(ieee, hdr, stats);
801 return 0; 812 dev_kfree_skb_irq(skb);
813 return;
802 case IEEE80211_FTYPE_DATA: 814 case IEEE80211_FTYPE_DATA:
803 break; 815 break;
804 case IEEE80211_FTYPE_CTL: 816 case IEEE80211_FTYPE_CTL:
805 return 0; 817 return;
806 default: 818 default:
807 return -EINVAL; 819 return;
808 } 820 }
809 821
810 is_packet_for_us = 0; 822 is_packet_for_us = 0;
@@ -848,8 +860,14 @@ int ieee80211_rx_any(struct ieee80211_device *ieee,
848 } 860 }
849 861
850 if (is_packet_for_us) 862 if (is_packet_for_us)
851 return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL); 863 if (!ieee80211_rx(ieee, skb, stats))
852 return 0; 864 dev_kfree_skb_irq(skb);
865 return;
866
867drop_free:
868 dev_kfree_skb_irq(skb);
869 ieee->stats.rx_dropped++;
870 return;
853} 871}
854 872
855#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 873#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
@@ -1060,13 +1078,16 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1060 1078
1061 while (length >= sizeof(*info_element)) { 1079 while (length >= sizeof(*info_element)) {
1062 if (sizeof(*info_element) + info_element->len > length) { 1080 if (sizeof(*info_element) + info_element->len > length) {
1063 IEEE80211_DEBUG_MGMT("Info elem: parse failed: " 1081 IEEE80211_ERROR("Info elem: parse failed: "
1064 "info_element->len + 2 > left : " 1082 "info_element->len + 2 > left : "
1065 "info_element->len+2=%zd left=%d, id=%d.\n", 1083 "info_element->len+2=%zd left=%d, id=%d.\n",
1066 info_element->len + 1084 info_element->len +
1067 sizeof(*info_element), 1085 sizeof(*info_element),
1068 length, info_element->id); 1086 length, info_element->id);
1069 return 1; 1087 /* We stop processing but don't return an error here
1088 * because some misbehaviour APs break this rule. ie.
1089 * Orinoco AP1000. */
1090 break;
1070 } 1091 }
1071 1092
1072 switch (info_element->id) { 1093 switch (info_element->id) {
@@ -1165,6 +1186,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1165 1186
1166 case MFIE_TYPE_ERP_INFO: 1187 case MFIE_TYPE_ERP_INFO:
1167 network->erp_value = info_element->data[0]; 1188 network->erp_value = info_element->data[0];
1189 network->flags |= NETWORK_HAS_ERP_VALUE;
1168 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", 1190 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1169 network->erp_value); 1191 network->erp_value);
1170 break; 1192 break;
@@ -1728,5 +1750,6 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1728 } 1750 }
1729} 1751}
1730 1752
1753EXPORT_SYMBOL_GPL(ieee80211_rx_any);
1731EXPORT_SYMBOL(ieee80211_rx_mgt); 1754EXPORT_SYMBOL(ieee80211_rx_mgt);
1732EXPORT_SYMBOL(ieee80211_rx); 1755EXPORT_SYMBOL(ieee80211_rx);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 6a5de1b84459..ae254497ba3d 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -24,7 +24,6 @@
24 24
25******************************************************************************/ 25******************************************************************************/
26#include <linux/compiler.h> 26#include <linux/compiler.h>
27#include <linux/config.h>
28#include <linux/errno.h> 27#include <linux/errno.h>
29#include <linux/if_arp.h> 28#include <linux/if_arp.h>
30#include <linux/in6.h> 29#include <linux/in6.h>
@@ -338,7 +337,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
338 hdr_len += 2; 337 hdr_len += 2;
339 338
340 skb->priority = ieee80211_classify(skb); 339 skb->priority = ieee80211_classify(skb);
341 header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID; 340 header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID);
342 } 341 }
343 header.frame_ctl = cpu_to_le16(fc); 342 header.frame_ctl = cpu_to_le16(fc);
344 343
@@ -533,13 +532,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
533 return 0; 532 return 0;
534 } 533 }
535 534
536 if (ret == NETDEV_TX_BUSY) {
537 printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
538 "driver should report queue full via "
539 "ieee_device->is_queue_full.\n",
540 ieee->dev->name);
541 }
542
543 ieee80211_txb_free(txb); 535 ieee80211_txb_free(txb);
544 } 536 }
545 537
@@ -563,10 +555,13 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
563 struct net_device_stats *stats = &ieee->stats; 555 struct net_device_stats *stats = &ieee->stats;
564 struct sk_buff *skb_frag; 556 struct sk_buff *skb_frag;
565 int priority = -1; 557 int priority = -1;
558 int fraglen = total_len;
559 int headroom = ieee->tx_headroom;
560 struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
566 561
567 spin_lock_irqsave(&ieee->lock, flags); 562 spin_lock_irqsave(&ieee->lock, flags);
568 563
569 if (encrypt_mpdu && !ieee->sec.encrypt) 564 if (encrypt_mpdu && (!ieee->sec.encrypt || !crypt))
570 encrypt_mpdu = 0; 565 encrypt_mpdu = 0;
571 566
572 /* If there is no driver handler to take the TXB, dont' bother 567 /* If there is no driver handler to take the TXB, dont' bother
@@ -582,20 +577,24 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
582 goto success; 577 goto success;
583 } 578 }
584 579
585 if (encrypt_mpdu) 580 if (encrypt_mpdu) {
586 frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 581 frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
582 fraglen += crypt->ops->extra_mpdu_prefix_len +
583 crypt->ops->extra_mpdu_postfix_len;
584 headroom += crypt->ops->extra_mpdu_prefix_len;
585 }
587 586
588 /* When we allocate the TXB we allocate enough space for the reserve 587 /* When we allocate the TXB we allocate enough space for the reserve
589 * and full fragment bytes (bytes_per_frag doesn't include prefix, 588 * and full fragment bytes (bytes_per_frag doesn't include prefix,
590 * postfix, header, FCS, etc.) */ 589 * postfix, header, FCS, etc.) */
591 txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC); 590 txb = ieee80211_alloc_txb(1, fraglen, headroom, GFP_ATOMIC);
592 if (unlikely(!txb)) { 591 if (unlikely(!txb)) {
593 printk(KERN_WARNING "%s: Could not allocate TXB\n", 592 printk(KERN_WARNING "%s: Could not allocate TXB\n",
594 ieee->dev->name); 593 ieee->dev->name);
595 goto failed; 594 goto failed;
596 } 595 }
597 txb->encrypted = 0; 596 txb->encrypted = 0;
598 txb->payload_size = total_len; 597 txb->payload_size = fraglen;
599 598
600 skb_frag = txb->fragments[0]; 599 skb_frag = txb->fragments[0];
601 600
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index a78c4f845f66..5cb9cfd35397 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -369,11 +369,10 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
369 struct ieee80211_crypt_data *new_crypt; 369 struct ieee80211_crypt_data *new_crypt;
370 370
371 /* take WEP into use */ 371 /* take WEP into use */
372 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data), 372 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
373 GFP_KERNEL); 373 GFP_KERNEL);
374 if (new_crypt == NULL) 374 if (new_crypt == NULL)
375 return -ENOMEM; 375 return -ENOMEM;
376 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
377 new_crypt->ops = ieee80211_get_crypto_ops("WEP"); 376 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
378 if (!new_crypt->ops) { 377 if (!new_crypt->ops) {
379 request_module("ieee80211_crypt_wep"); 378 request_module("ieee80211_crypt_wep");
@@ -616,13 +615,11 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
616 615
617 ieee80211_crypt_delayed_deinit(ieee, crypt); 616 ieee80211_crypt_delayed_deinit(ieee, crypt);
618 617
619 new_crypt = (struct ieee80211_crypt_data *) 618 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
620 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
621 if (new_crypt == NULL) { 619 if (new_crypt == NULL) {
622 ret = -ENOMEM; 620 ret = -ENOMEM;
623 goto done; 621 goto done;
624 } 622 }
625 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
626 new_crypt->ops = ops; 623 new_crypt->ops = ops;
627 if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) 624 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
628 new_crypt->priv = new_crypt->ops->init(idx); 625 new_crypt->priv = new_crypt->ops->init(idx);
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 5e9a90651d04..589f6d2c548a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -47,9 +47,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
47 47
48 dprintk(KERN_INFO PFX "sent association request!\n"); 48 dprintk(KERN_INFO PFX "sent association request!\n");
49 49
50 /* Change the state to associating */
51 spin_lock_irqsave(&mac->lock, flags); 50 spin_lock_irqsave(&mac->lock, flags);
52 mac->associnfo.associating = 1;
53 mac->associated = 0; /* just to make sure */ 51 mac->associated = 0; /* just to make sure */
54 52
55 /* Set a timer for timeout */ 53 /* Set a timer for timeout */
@@ -63,6 +61,7 @@ void
63ieee80211softmac_assoc_timeout(void *d) 61ieee80211softmac_assoc_timeout(void *d)
64{ 62{
65 struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; 63 struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
64 struct ieee80211softmac_network *n;
66 unsigned long flags; 65 unsigned long flags;
67 66
68 spin_lock_irqsave(&mac->lock, flags); 67 spin_lock_irqsave(&mac->lock, flags);
@@ -75,11 +74,12 @@ ieee80211softmac_assoc_timeout(void *d)
75 mac->associnfo.associating = 0; 74 mac->associnfo.associating = 0;
76 mac->associnfo.bssvalid = 0; 75 mac->associnfo.bssvalid = 0;
77 mac->associated = 0; 76 mac->associated = 0;
77
78 n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
78 spin_unlock_irqrestore(&mac->lock, flags); 79 spin_unlock_irqrestore(&mac->lock, flags);
79 80
80 dprintk(KERN_INFO PFX "assoc request timed out!\n"); 81 dprintk(KERN_INFO PFX "assoc request timed out!\n");
81 /* FIXME: we need to know the network here. that requires a bit of restructuring */ 82 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
82 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
83} 83}
84 84
85void 85void
@@ -96,7 +96,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
96 mac->associated = 0; 96 mac->associated = 0;
97 mac->associnfo.bssvalid = 0; 97 mac->associnfo.bssvalid = 0;
98 mac->associnfo.associating = 0; 98 mac->associnfo.associating = 0;
99 ieee80211softmac_init_txrates(mac); 99 ieee80211softmac_init_bss(mac);
100 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); 100 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
101 spin_unlock_irqrestore(&mac->lock, flags); 101 spin_unlock_irqrestore(&mac->lock, flags);
102} 102}
@@ -203,6 +203,10 @@ ieee80211softmac_assoc_work(void *d)
203 if (mac->associated) 203 if (mac->associated)
204 ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); 204 ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
205 205
206 spin_lock_irqsave(&mac->lock, flags);
207 mac->associnfo.associating = 1;
208 spin_unlock_irqrestore(&mac->lock, flags);
209
206 /* try to find the requested network in our list, if we found one already */ 210 /* try to find the requested network in our list, if we found one already */
207 if (bssvalid || mac->associnfo.bssfixed) 211 if (bssvalid || mac->associnfo.bssfixed)
208 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); 212 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
@@ -295,19 +299,32 @@ ieee80211softmac_assoc_work(void *d)
295 memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); 299 memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
296 300
297 /* we found a network! authenticate (if necessary) and associate to it. */ 301 /* we found a network! authenticate (if necessary) and associate to it. */
298 if (!found->authenticated) { 302 if (found->authenticating) {
303 dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
304 if(!mac->associnfo.assoc_wait) {
305 mac->associnfo.assoc_wait = 1;
306 ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
307 }
308 return;
309 }
310 if (!found->authenticated && !found->authenticating) {
299 /* This relies on the fact that _auth_req only queues the work, 311 /* This relies on the fact that _auth_req only queues the work,
300 * otherwise adding the notification would be racy. */ 312 * otherwise adding the notification would be racy. */
301 if (!ieee80211softmac_auth_req(mac, found)) { 313 if (!ieee80211softmac_auth_req(mac, found)) {
302 dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n"); 314 if(!mac->associnfo.assoc_wait) {
303 ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); 315 dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n");
316 mac->associnfo.assoc_wait = 1;
317 ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
318 }
304 } else { 319 } else {
305 printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); 320 printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
321 mac->associnfo.assoc_wait = 0;
306 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); 322 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
307 } 323 }
308 return; 324 return;
309 } 325 }
310 /* finally! now we can start associating */ 326 /* finally! now we can start associating */
327 mac->associnfo.assoc_wait = 0;
311 ieee80211softmac_assoc(mac, found); 328 ieee80211softmac_assoc(mac, found);
312} 329}
313 330
@@ -317,11 +334,19 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
317 struct ieee80211_assoc_response * resp, 334 struct ieee80211_assoc_response * resp,
318 struct ieee80211softmac_network *net) 335 struct ieee80211softmac_network *net)
319{ 336{
337 u16 cap = le16_to_cpu(resp->capability);
338 u8 erp_value = net->erp_value;
339
320 mac->associnfo.associating = 0; 340 mac->associnfo.associating = 0;
321 mac->associnfo.supported_rates = net->supported_rates; 341 mac->bssinfo.supported_rates = net->supported_rates;
322 ieee80211softmac_recalc_txrates(mac); 342 ieee80211softmac_recalc_txrates(mac);
323 343
324 mac->associated = 1; 344 mac->associated = 1;
345
346 mac->associnfo.short_preamble_available =
347 (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
348 ieee80211softmac_process_erp(mac, erp_value);
349
325 if (mac->set_bssid_filter) 350 if (mac->set_bssid_filter)
326 mac->set_bssid_filter(mac->dev, net->bssid); 351 mac->set_bssid_filter(mac->dev, net->bssid);
327 memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN); 352 memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
@@ -334,9 +359,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
334int 359int
335ieee80211softmac_handle_assoc_response(struct net_device * dev, 360ieee80211softmac_handle_assoc_response(struct net_device * dev,
336 struct ieee80211_assoc_response * resp, 361 struct ieee80211_assoc_response * resp,
337 struct ieee80211_network * _ieee80211_network_do_not_use) 362 struct ieee80211_network * _ieee80211_network)
338{ 363{
339 /* NOTE: the network parameter has to be ignored by 364 /* NOTE: the network parameter has to be mostly ignored by
340 * this code because it is the ieee80211's pointer 365 * this code because it is the ieee80211's pointer
341 * to the struct, not ours (we made a copy) 366 * to the struct, not ours (we made a copy)
342 */ 367 */
@@ -368,6 +393,11 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
368 /* now that we know it was for us, we can cancel the timeout */ 393 /* now that we know it was for us, we can cancel the timeout */
369 cancel_delayed_work(&mac->associnfo.timeout); 394 cancel_delayed_work(&mac->associnfo.timeout);
370 395
396 /* if the association response included an ERP IE, update our saved
397 * copy */
398 if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE)
399 network->erp_value = _ieee80211_network->erp_value;
400
371 switch (status) { 401 switch (status) {
372 case 0: 402 case 0:
373 dprintk(KERN_INFO PFX "associated!\n"); 403 dprintk(KERN_INFO PFX "associated!\n");
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 90b8484e509b..4cef39e171d0 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -36,8 +36,9 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
36 struct ieee80211softmac_auth_queue_item *auth; 36 struct ieee80211softmac_auth_queue_item *auth;
37 unsigned long flags; 37 unsigned long flags;
38 38
39 if (net->authenticating) 39 if (net->authenticating || net->authenticated)
40 return 0; 40 return 0;
41 net->authenticating = 1;
41 42
42 /* Add the network if it's not already added */ 43 /* Add the network if it's not already added */
43 ieee80211softmac_add_network(mac, net); 44 ieee80211softmac_add_network(mac, net);
@@ -92,7 +93,6 @@ ieee80211softmac_auth_queue(void *data)
92 return; 93 return;
93 } 94 }
94 net->authenticated = 0; 95 net->authenticated = 0;
95 net->authenticating = 1;
96 /* add a timeout call so we eventually give up waiting for an auth reply */ 96 /* add a timeout call so we eventually give up waiting for an auth reply */
97 schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); 97 schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
98 auth->retry--; 98 auth->retry--;
@@ -116,6 +116,16 @@ ieee80211softmac_auth_queue(void *data)
116 kfree(auth); 116 kfree(auth);
117} 117}
118 118
119/* Sends a response to an auth challenge (for shared key auth). */
120static void
121ieee80211softmac_auth_challenge_response(void *_aq)
122{
123 struct ieee80211softmac_auth_queue_item *aq = _aq;
124
125 /* Send our response */
126 ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
127}
128
119/* Handle the auth response from the AP 129/* Handle the auth response from the AP
120 * This should be registered with ieee80211 as handle_auth 130 * This should be registered with ieee80211 as handle_auth
121 */ 131 */
@@ -197,24 +207,30 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
197 case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE: 207 case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
198 /* Check to make sure we have a challenge IE */ 208 /* Check to make sure we have a challenge IE */
199 data = (u8 *)auth->info_element; 209 data = (u8 *)auth->info_element;
200 if(*data++ != MFIE_TYPE_CHALLENGE){ 210 if (*data++ != MFIE_TYPE_CHALLENGE) {
201 printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n"); 211 printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
202 break; 212 break;
203 } 213 }
204 /* Save the challenge */ 214 /* Save the challenge */
205 spin_lock_irqsave(&mac->lock, flags); 215 spin_lock_irqsave(&mac->lock, flags);
206 net->challenge_len = *data++; 216 net->challenge_len = *data++;
207 if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) 217 if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
208 net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; 218 net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
209 if(net->challenge != NULL) 219 if (net->challenge != NULL)
210 kfree(net->challenge); 220 kfree(net->challenge);
211 net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); 221 net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC);
212 memcpy(net->challenge, data, net->challenge_len); 222 memcpy(net->challenge, data, net->challenge_len);
213 aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; 223 aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
214 spin_unlock_irqrestore(&mac->lock, flags);
215 224
216 /* Send our response */ 225 /* We reuse the work struct from the auth request here.
217 ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); 226 * It is safe to do so as each one is per-request, and
227 * at this point (dealing with authentication response)
228 * we have obviously already sent the initial auth
229 * request. */
230 cancel_delayed_work(&aq->work);
231 INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq);
232 schedule_work(&aq->work);
233 spin_unlock_irqrestore(&mac->lock, flags);
218 return 0; 234 return 0;
219 case IEEE80211SOFTMAC_AUTH_SHARED_PASS: 235 case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
220 kfree(net->challenge); 236 kfree(net->challenge);
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index 09541611e48c..82bfddbf33a2 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -96,8 +96,7 @@ ieee80211softmac_alloc_mgt(u32 size)
96 if(size > IEEE80211_DATA_LEN) 96 if(size > IEEE80211_DATA_LEN)
97 return NULL; 97 return NULL;
98 /* Allocate the frame */ 98 /* Allocate the frame */
99 data = kmalloc(size, GFP_ATOMIC); 99 data = kzalloc(size, GFP_ATOMIC);
100 memset(data, 0, size);
101 return data; 100 return data;
102} 101}
103 102
@@ -229,6 +228,9 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
229 return 0; 228 return 0;
230 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); 229 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
231 230
231 /* Fill in the capabilities */
232 (*pkt)->capability = ieee80211softmac_capabilities(mac, net);
233
232 /* Fill in Listen Interval (?) */ 234 /* Fill in Listen Interval (?) */
233 (*pkt)->listen_interval = cpu_to_le16(10); 235 (*pkt)->listen_interval = cpu_to_le16(10);
234 236
@@ -465,3 +467,17 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
465 kfree(pkt); 467 kfree(pkt);
466 return 0; 468 return 0;
467} 469}
470
471/* Beacon handling */
472int ieee80211softmac_handle_beacon(struct net_device *dev,
473 struct ieee80211_beacon *beacon,
474 struct ieee80211_network *network)
475{
476 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
477
478 if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
479 ieee80211softmac_process_erp(mac, network->erp_value);
480
481 return 0;
482}
483
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 4b2e57d12418..addea1cf73ae 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -44,6 +44,7 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
44 softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response; 44 softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
45 softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req; 45 softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
46 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; 46 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
47 softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
47 softmac->scaninfo = NULL; 48 softmac->scaninfo = NULL;
48 49
49 softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; 50 softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
@@ -178,21 +179,14 @@ int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo
178 return 0; 179 return 0;
179} 180}
180 181
181/* Finds the highest rate which is: 182u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
182 * 1. Present in ri (optionally a basic rate)
183 * 2. Supported by the device
184 * 3. Less than or equal to the user-defined rate
185 */
186static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
187 struct ieee80211softmac_ratesinfo *ri, int basic_only) 183 struct ieee80211softmac_ratesinfo *ri, int basic_only)
188{ 184{
189 u8 user_rate = mac->txrates.user_rate; 185 u8 user_rate = mac->txrates.user_rate;
190 int i; 186 int i;
191 187
192 if (ri->count == 0) { 188 if (ri->count == 0)
193 dprintk(KERN_ERR PFX "empty ratesinfo?\n");
194 return IEEE80211_CCK_RATE_1MB; 189 return IEEE80211_CCK_RATE_1MB;
195 }
196 190
197 for (i = ri->count - 1; i >= 0; i--) { 191 for (i = ri->count - 1; i >= 0; i--) {
198 u8 rate = ri->rates[i]; 192 u8 rate = ri->rates[i];
@@ -208,36 +202,61 @@ static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
208 /* If we haven't found a suitable rate by now, just trust the user */ 202 /* If we haven't found a suitable rate by now, just trust the user */
209 return user_rate; 203 return user_rate;
210} 204}
205EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
206
207void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
208 u8 erp_value)
209{
210 int use_protection;
211 int short_preamble;
212 u32 changes = 0;
213
214 /* Barker preamble mode */
215 short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
216 && mac->associnfo.short_preamble_available) ? 1 : 0;
217
218 /* Protection needed? */
219 use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
220
221 if (mac->bssinfo.short_preamble != short_preamble) {
222 changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
223 mac->bssinfo.short_preamble = short_preamble;
224 }
225
226 if (mac->bssinfo.use_protection != use_protection) {
227 changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
228 mac->bssinfo.use_protection = use_protection;
229 }
230
231 if (mac->bssinfo_change && changes)
232 mac->bssinfo_change(mac->dev, changes);
233}
211 234
212void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac) 235void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
213{ 236{
214 struct ieee80211softmac_txrates *txrates = &mac->txrates; 237 struct ieee80211softmac_txrates *txrates = &mac->txrates;
215 struct ieee80211softmac_txrates oldrates;
216 u32 change = 0; 238 u32 change = 0;
217 239
218 if (mac->txrates_change)
219 oldrates = mac->txrates;
220
221 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; 240 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
222 txrates->default_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 0); 241 txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
223 242
224 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; 243 change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
225 txrates->default_fallback = lower_rate(mac, txrates->default_rate); 244 txrates->default_fallback = lower_rate(mac, txrates->default_rate);
226 245
227 change |= IEEE80211SOFTMAC_TXRATECHG_MCAST; 246 change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
228 txrates->mcast_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 1); 247 txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
229 248
230 if (mac->txrates_change) 249 if (mac->txrates_change)
231 mac->txrates_change(mac->dev, change, &oldrates); 250 mac->txrates_change(mac->dev, change);
232 251
233} 252}
234 253
235void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac) 254void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
236{ 255{
237 struct ieee80211_device *ieee = mac->ieee; 256 struct ieee80211_device *ieee = mac->ieee;
238 u32 change = 0; 257 u32 change = 0;
239 struct ieee80211softmac_txrates *txrates = &mac->txrates; 258 struct ieee80211softmac_txrates *txrates = &mac->txrates;
240 struct ieee80211softmac_txrates oldrates; 259 struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
241 260
242 /* TODO: We need some kind of state machine to lower the default rates 261 /* TODO: We need some kind of state machine to lower the default rates
243 * if we loose too many packets. 262 * if we loose too many packets.
@@ -245,8 +264,6 @@ void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
245 /* Change the default txrate to the highest possible value. 264 /* Change the default txrate to the highest possible value.
246 * The txrate machine will lower it, if it is too high. 265 * The txrate machine will lower it, if it is too high.
247 */ 266 */
248 if (mac->txrates_change)
249 oldrates = mac->txrates;
250 /* FIXME: We don't correctly handle backing down to lower 267 /* FIXME: We don't correctly handle backing down to lower
251 rates, so 801.11g devices start off at 11M for now. People 268 rates, so 801.11g devices start off at 11M for now. People
252 can manually change it if they really need to, but 11M is 269 can manually change it if they really need to, but 11M is
@@ -272,7 +289,23 @@ void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
272 change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST; 289 change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
273 290
274 if (mac->txrates_change) 291 if (mac->txrates_change)
275 mac->txrates_change(mac->dev, change, &oldrates); 292 mac->txrates_change(mac->dev, change);
293
294 change = 0;
295
296 bssinfo->supported_rates.count = 0;
297 memset(bssinfo->supported_rates.rates, 0,
298 sizeof(bssinfo->supported_rates.rates));
299 change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
300
301 bssinfo->short_preamble = 0;
302 change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
303
304 bssinfo->use_protection = 0;
305 change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
306
307 if (mac->bssinfo_change)
308 mac->bssinfo_change(mac->dev, change);
276 309
277 mac->running = 1; 310 mac->running = 1;
278} 311}
@@ -282,7 +315,7 @@ void ieee80211softmac_start(struct net_device *dev)
282 struct ieee80211softmac_device *mac = ieee80211_priv(dev); 315 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
283 316
284 ieee80211softmac_start_check_rates(mac); 317 ieee80211softmac_start_check_rates(mac);
285 ieee80211softmac_init_txrates(mac); 318 ieee80211softmac_init_bss(mac);
286} 319}
287EXPORT_SYMBOL_GPL(ieee80211softmac_start); 320EXPORT_SYMBOL_GPL(ieee80211softmac_start);
288 321
@@ -335,7 +368,6 @@ u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rat
335static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac, 368static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
336 int amount) 369 int amount)
337{ 370{
338 struct ieee80211softmac_txrates oldrates;
339 u8 default_rate = mac->txrates.default_rate; 371 u8 default_rate = mac->txrates.default_rate;
340 u8 default_fallback = mac->txrates.default_fallback; 372 u8 default_fallback = mac->txrates.default_fallback;
341 u32 changes = 0; 373 u32 changes = 0;
@@ -348,8 +380,6 @@ printk("badness %d\n", mac->txrate_badness);
348 mac->txrate_badness += amount; 380 mac->txrate_badness += amount;
349 if (mac->txrate_badness <= -1000) { 381 if (mac->txrate_badness <= -1000) {
350 /* Very small badness. Try a faster bitrate. */ 382 /* Very small badness. Try a faster bitrate. */
351 if (mac->txrates_change)
352 memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
353 default_rate = raise_rate(mac, default_rate); 383 default_rate = raise_rate(mac, default_rate);
354 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; 384 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
355 default_fallback = get_fallback_rate(mac, default_rate); 385 default_fallback = get_fallback_rate(mac, default_rate);
@@ -358,8 +388,6 @@ printk("badness %d\n", mac->txrate_badness);
358printk("Bitrate raised to %u\n", default_rate); 388printk("Bitrate raised to %u\n", default_rate);
359 } else if (mac->txrate_badness >= 10000) { 389 } else if (mac->txrate_badness >= 10000) {
360 /* Very high badness. Try a slower bitrate. */ 390 /* Very high badness. Try a slower bitrate. */
361 if (mac->txrates_change)
362 memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
363 default_rate = lower_rate(mac, default_rate); 391 default_rate = lower_rate(mac, default_rate);
364 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; 392 changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
365 default_fallback = get_fallback_rate(mac, default_rate); 393 default_fallback = get_fallback_rate(mac, default_rate);
@@ -372,7 +400,7 @@ printk("Bitrate lowered to %u\n", default_rate);
372 mac->txrates.default_fallback = default_fallback; 400 mac->txrates.default_fallback = default_fallback;
373 401
374 if (changes && mac->txrates_change) 402 if (changes && mac->txrates_change)
375 mac->txrates_change(mac->dev, changes, &oldrates); 403 mac->txrates_change(mac->dev, changes);
376} 404}
377 405
378void ieee80211softmac_fragment_lost(struct net_device *dev, 406void ieee80211softmac_fragment_lost(struct net_device *dev,
@@ -416,7 +444,11 @@ ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
416 memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len); 444 memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
417 softnet->supported_rates.count += net->rates_ex_len; 445 softnet->supported_rates.count += net->rates_ex_len;
418 sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL); 446 sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
419 447
448 /* we save the ERP value because it is needed at association time, and
449 * many AP's do not include an ERP IE in the association response. */
450 softnet->erp_value = net->erp_value;
451
420 softnet->capabilities = net->capability; 452 softnet->capabilities = net->capability;
421 return softnet; 453 return softnet;
422} 454}
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
index fa1f8e3acfc0..0642e090b8a7 100644
--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -116,9 +116,11 @@ ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
116 struct ieee80211softmac_essid *essid); 116 struct ieee80211softmac_essid *essid);
117 117
118/* Rates related */ 118/* Rates related */
119void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
120 u8 erp_value);
119int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate); 121int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
120u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta); 122u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
121void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac); 123void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac);
122void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac); 124void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
123static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) { 125static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
124 return ieee80211softmac_lower_rate_delta(mac, rate, 1); 126 return ieee80211softmac_lower_rate_delta(mac, rate, 1);
@@ -133,6 +135,9 @@ static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate)
133/*** prototypes from _io.c */ 135/*** prototypes from _io.c */
134int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, 136int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
135 void* ptrarg, u32 type, u32 arg); 137 void* ptrarg, u32 type, u32 arg);
138int ieee80211softmac_handle_beacon(struct net_device *dev,
139 struct ieee80211_beacon *beacon,
140 struct ieee80211_network *network);
136 141
137/*** prototypes from _auth.c */ 142/*** prototypes from _auth.c */
138/* do these have to go into the public header? */ 143/* do these have to go into the public header? */
@@ -189,6 +194,7 @@ struct ieee80211softmac_network {
189 authenticated:1, 194 authenticated:1,
190 auth_desynced_once:1; 195 auth_desynced_once:1;
191 196
197 u8 erp_value; /* Saved ERP value */
192 u16 capabilities; /* Capabilities bitfield */ 198 u16 capabilities; /* Capabilities bitfield */
193 u8 challenge_len; /* Auth Challenge length */ 199 u8 challenge_len; /* Auth Challenge length */
194 char *challenge; /* Challenge Text */ 200 char *challenge; /* Challenge Text */
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 0e65ff4e33fc..2aa779d18f38 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -70,15 +70,47 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
70 char *extra) 70 char *extra)
71{ 71{
72 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); 72 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
73 struct ieee80211softmac_network *n;
74 struct ieee80211softmac_auth_queue_item *authptr;
73 int length = 0; 75 int length = 0;
74 unsigned long flags; 76 unsigned long flags;
75 77
78 /* Check if we're already associating to this or another network
79 * If it's another network, cancel and start over with our new network
80 * If it's our network, ignore the change, we're already doing it!
81 */
82 if((sm->associnfo.associating || sm->associated) &&
83 (data->essid.flags && data->essid.length)) {
84 /* Get the associating network */
85 n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
86 if(n && n->essid.len == data->essid.length &&
87 !memcmp(n->essid.data, extra, n->essid.len)) {
88 dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
89 MAC_ARG(sm->associnfo.bssid));
90 return 0;
91 } else {
92 dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
93 spin_lock_irqsave(&sm->lock,flags);
94 /* Cancel assoc work */
95 cancel_delayed_work(&sm->associnfo.work);
96 /* We don't have to do this, but it's a little cleaner */
97 list_for_each_entry(authptr, &sm->auth_queue, list)
98 cancel_delayed_work(&authptr->work);
99 sm->associnfo.bssvalid = 0;
100 sm->associnfo.bssfixed = 0;
101 spin_unlock_irqrestore(&sm->lock,flags);
102 flush_scheduled_work();
103 }
104 }
105
106
76 spin_lock_irqsave(&sm->lock, flags); 107 spin_lock_irqsave(&sm->lock, flags);
77 108
78 sm->associnfo.static_essid = 0; 109 sm->associnfo.static_essid = 0;
110 sm->associnfo.assoc_wait = 0;
79 111
80 if (data->essid.flags && data->essid.length && extra /*required?*/) { 112 if (data->essid.flags && data->essid.length) {
81 length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE); 113 length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
82 if (length) { 114 if (length) {
83 memcpy(sm->associnfo.req_essid.data, extra, length); 115 memcpy(sm->associnfo.req_essid.data, extra, length);
84 sm->associnfo.static_essid = 1; 116 sm->associnfo.static_essid = 1;