aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c23
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c114
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c38
-rw-r--r--net/ieee80211/ieee80211_rx.c56
-rw-r--r--net/ieee80211/ieee80211_tx.c9
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c21
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c14
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c90
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_priv.h8
9 files changed, 267 insertions, 106 deletions
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index fdfe7704a469..35aa3426c3fa 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -263,6 +263,27 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
263 return 0; 263 return 0;
264} 264}
265 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
266static 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)
267{ 288{
268 struct ieee80211_ccmp_data *key = priv; 289 struct ieee80211_ccmp_data *key = priv;
@@ -315,7 +336,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
315 pn[5] = pos[0]; 336 pn[5] = pos[0];
316 pos += 8; 337 pos += 8;
317 338
318 if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { 339 if (ccmp_replay_check(pn, key->rx_pn)) {
319 if (net_ratelimit()) { 340 if (net_ratelimit()) {
320 printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT 341 printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
321 " previous PN %02x%02x%02x%02x%02x%02x " 342 " previous PN %02x%02x%02x%02x%02x%02x "
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 407a17495b61..4200ec509866 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -53,8 +53,10 @@ struct ieee80211_tkip_data {
53 53
54 int key_idx; 54 int key_idx;
55 55
56 struct crypto_blkcipher *tfm_arc4; 56 struct crypto_blkcipher *rx_tfm_arc4;
57 struct crypto_hash *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,21 +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_blkcipher("ecb(arc4)", 0, 91 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
90 CRYPTO_ALG_ASYNC); 92 CRYPTO_ALG_ASYNC);
91 if (IS_ERR(priv->tfm_arc4)) { 93 if (IS_ERR(priv->tx_tfm_arc4)) {
92 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 94 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
93 "crypto API arc4\n"); 95 "crypto API arc4\n");
94 priv->tfm_arc4 = NULL; 96 priv->tx_tfm_arc4 = NULL;
95 goto fail; 97 goto fail;
96 } 98 }
97 99
98 priv->tfm_michael = crypto_alloc_hash("michael_mic", 0, 100 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
99 CRYPTO_ALG_ASYNC); 101 CRYPTO_ALG_ASYNC);
100 if (IS_ERR(priv->tfm_michael)) { 102 if (IS_ERR(priv->tx_tfm_michael)) {
101 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 103 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
102 "crypto API michael_mic\n"); 104 "crypto API michael_mic\n");
103 priv->tfm_michael = NULL; 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;
104 goto fail; 124 goto fail;
105 } 125 }
106 126
@@ -108,10 +128,14 @@ static void *ieee80211_tkip_init(int key_idx)
108 128
109 fail: 129 fail:
110 if (priv) { 130 if (priv) {
111 if (priv->tfm_michael) 131 if (priv->tx_tfm_michael)
112 crypto_free_hash(priv->tfm_michael); 132 crypto_free_hash(priv->tx_tfm_michael);
113 if (priv->tfm_arc4) 133 if (priv->tx_tfm_arc4)
114 crypto_free_blkcipher(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);
115 kfree(priv); 139 kfree(priv);
116 } 140 }
117 141
@@ -121,10 +145,16 @@ static void *ieee80211_tkip_init(int key_idx)
121static void ieee80211_tkip_deinit(void *priv) 145static void ieee80211_tkip_deinit(void *priv)
122{ 146{
123 struct ieee80211_tkip_data *_priv = priv; 147 struct ieee80211_tkip_data *_priv = priv;
124 if (_priv && _priv->tfm_michael) 148 if (_priv) {
125 crypto_free_hash(_priv->tfm_michael); 149 if (_priv->tx_tfm_michael)
126 if (_priv && _priv->tfm_arc4) 150 crypto_free_hash(_priv->tx_tfm_michael);
127 crypto_free_blkcipher(_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 }
128 kfree(priv); 158 kfree(priv);
129} 159}
130 160
@@ -323,7 +353,7 @@ static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
323static 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)
324{ 354{
325 struct ieee80211_tkip_data *tkey = priv; 355 struct ieee80211_tkip_data *tkey = priv;
326 struct blkcipher_desc desc = { .tfm = tkey->tfm_arc4 }; 356 struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
327 int len; 357 int len;
328 u8 rc4key[16], *pos, *icv; 358 u8 rc4key[16], *pos, *icv;
329 u32 crc; 359 u32 crc;
@@ -357,17 +387,30 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
357 icv[2] = crc >> 16; 387 icv[2] = crc >> 16;
358 icv[3] = crc >> 24; 388 icv[3] = crc >> 24;
359 389
360 crypto_blkcipher_setkey(tkey->tfm_arc4, rc4key, 16); 390 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
361 sg.page = virt_to_page(pos); 391 sg.page = virt_to_page(pos);
362 sg.offset = offset_in_page(pos); 392 sg.offset = offset_in_page(pos);
363 sg.length = len + 4; 393 sg.length = len + 4;
364 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); 394 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
365} 395}
366 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;
407 return 0;
408}
409
367static 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)
368{ 411{
369 struct ieee80211_tkip_data *tkey = priv; 412 struct ieee80211_tkip_data *tkey = priv;
370 struct blkcipher_desc desc = { .tfm = tkey->tfm_arc4 }; 413 struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
371 u8 rc4key[16]; 414 u8 rc4key[16];
372 u8 keyidx, *pos; 415 u8 keyidx, *pos;
373 u32 iv32; 416 u32 iv32;
@@ -419,8 +462,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
419 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);
420 pos += 8; 463 pos += 8;
421 464
422 if (iv32 < tkey->rx_iv32 || 465 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
423 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
424 if (net_ratelimit()) { 466 if (net_ratelimit()) {
425 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT 467 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
426 " previous TSC %08x%04x received TSC " 468 " previous TSC %08x%04x received TSC "
@@ -439,7 +481,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
439 481
440 plen = skb->len - hdr_len - 12; 482 plen = skb->len - hdr_len - 12;
441 483
442 crypto_blkcipher_setkey(tkey->tfm_arc4, rc4key, 16); 484 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
443 sg.page = virt_to_page(pos); 485 sg.page = virt_to_page(pos);
444 sg.offset = offset_in_page(pos); 486 sg.offset = offset_in_page(pos);
445 sg.length = plen + 4; 487 sg.length = plen + 4;
@@ -484,13 +526,13 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
484 return keyidx; 526 return keyidx;
485} 527}
486 528
487static 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,
488 u8 * data, size_t data_len, u8 * mic) 530 u8 * data, size_t data_len, u8 * mic)
489{ 531{
490 struct hash_desc desc; 532 struct hash_desc desc;
491 struct scatterlist sg[2]; 533 struct scatterlist sg[2];
492 534
493 if (tkey->tfm_michael == NULL) { 535 if (tfm_michael == NULL) {
494 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); 536 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
495 return -1; 537 return -1;
496 } 538 }
@@ -502,10 +544,10 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
502 sg[1].offset = offset_in_page(data); 544 sg[1].offset = offset_in_page(data);
503 sg[1].length = data_len; 545 sg[1].length = data_len;
504 546
505 if (crypto_hash_setkey(tkey->tfm_michael, key, 8)) 547 if (crypto_hash_setkey(tfm_michael, key, 8))
506 return -1; 548 return -1;
507 549
508 desc.tfm = tkey->tfm_michael; 550 desc.tfm = tfm_michael;
509 desc.flags = 0; 551 desc.flags = 0;
510 return crypto_hash_digest(&desc, sg, data_len + 16, mic); 552 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
511} 553}
@@ -541,7 +583,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
541 if (stype & IEEE80211_STYPE_QOS_DATA) { 583 if (stype & IEEE80211_STYPE_QOS_DATA) {
542 const struct ieee80211_hdr_3addrqos *qoshdr = 584 const struct ieee80211_hdr_3addrqos *qoshdr =
543 (struct ieee80211_hdr_3addrqos *)skb->data; 585 (struct ieee80211_hdr_3addrqos *)skb->data;
544 hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; 586 hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID);
545 } else 587 } else
546 hdr[12] = 0; /* priority */ 588 hdr[12] = 0; /* priority */
547 589
@@ -563,7 +605,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
563 605
564 michael_mic_hdr(skb, tkey->tx_hdr); 606 michael_mic_hdr(skb, tkey->tx_hdr);
565 pos = skb_put(skb, 8); 607 pos = skb_put(skb, 8);
566 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr, 608 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
567 skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) 609 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
568 return -1; 610 return -1;
569 611
@@ -601,7 +643,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
601 return -1; 643 return -1;
602 644
603 michael_mic_hdr(skb, tkey->rx_hdr); 645 michael_mic_hdr(skb, tkey->rx_hdr);
604 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr, 646 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
605 skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) 647 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
606 return -1; 648 return -1;
607 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { 649 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
@@ -631,14 +673,18 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
631{ 673{
632 struct ieee80211_tkip_data *tkey = priv; 674 struct ieee80211_tkip_data *tkey = priv;
633 int keyidx; 675 int keyidx;
634 struct crypto_hash *tfm = tkey->tfm_michael; 676 struct crypto_hash *tfm = tkey->tx_tfm_michael;
635 struct crypto_blkcipher *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;
636 680
637 keyidx = tkey->key_idx; 681 keyidx = tkey->key_idx;
638 memset(tkey, 0, sizeof(*tkey)); 682 memset(tkey, 0, sizeof(*tkey));
639 tkey->key_idx = keyidx; 683 tkey->key_idx = keyidx;
640 tkey->tfm_michael = tfm; 684 tkey->tx_tfm_michael = tfm;
641 tkey->tfm_arc4 = tfm2; 685 tkey->tx_tfm_arc4 = tfm2;
686 tkey->rx_tfm_michael = tfm3;
687 tkey->rx_tfm_arc4 = tfm4;
642 if (len == TKIP_KEY_LEN) { 688 if (len == TKIP_KEY_LEN) {
643 memcpy(tkey->key, key, TKIP_KEY_LEN); 689 memcpy(tkey->key, key, TKIP_KEY_LEN);
644 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 3d46d3efe1dd..1b2efff11d39 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -33,7 +33,8 @@ 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_blkcipher *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)
@@ -45,14 +46,21 @@ static void *prism2_wep_init(int keyidx)
45 goto fail; 46 goto fail;
46 priv->key_idx = keyidx; 47 priv->key_idx = keyidx;
47 48
48 priv->tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); 49 priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
49 if (IS_ERR(priv->tfm)) { 50 if (IS_ERR(priv->tx_tfm)) {
50 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " 51 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
51 "crypto API arc4\n"); 52 "crypto API arc4\n");
52 priv->tfm = NULL; 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_blkcipher(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_blkcipher(_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,7 +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;
125 struct blkcipher_desc desc = { .tfm = wep->tfm }; 139 struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
126 u32 crc, klen, len; 140 u32 crc, klen, len;
127 u8 *pos, *icv; 141 u8 *pos, *icv;
128 struct scatterlist sg; 142 struct scatterlist sg;
@@ -154,7 +168,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
154 icv[2] = crc >> 16; 168 icv[2] = crc >> 16;
155 icv[3] = crc >> 24; 169 icv[3] = crc >> 24;
156 170
157 crypto_blkcipher_setkey(wep->tfm, key, klen); 171 crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
158 sg.page = virt_to_page(pos); 172 sg.page = virt_to_page(pos);
159 sg.offset = offset_in_page(pos); 173 sg.offset = offset_in_page(pos);
160 sg.length = len + 4; 174 sg.length = len + 4;
@@ -171,7 +185,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
171static 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)
172{ 186{
173 struct prism2_wep_data *wep = priv; 187 struct prism2_wep_data *wep = priv;
174 struct blkcipher_desc desc = { .tfm = wep->tfm }; 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,7 +210,7 @@ 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_blkcipher_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;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 72d4d4e04d42..770704183a1b 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -779,33 +779,44 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
779 return 0; 779 return 0;
780} 780}
781 781
782/* Filter out unrelated packets, call ieee80211_rx[_mgt] */ 782/* Filter out unrelated packets, call ieee80211_rx[_mgt]
783int 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,
784 struct sk_buff *skb, struct ieee80211_rx_stats *stats) 786 struct sk_buff *skb, struct ieee80211_rx_stats *stats)
785{ 787{
786 struct ieee80211_hdr_4addr *hdr; 788 struct ieee80211_hdr_4addr *hdr;
787 int is_packet_for_us; 789 int is_packet_for_us;
788 u16 fc; 790 u16 fc;
789 791
790 if (ieee->iw_mode == IW_MODE_MONITOR) 792 if (ieee->iw_mode == IW_MODE_MONITOR) {
791 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;
792 800
793 hdr = (struct ieee80211_hdr_4addr *)skb->data; 801 hdr = (struct ieee80211_hdr_4addr *)skb->data;
794 fc = le16_to_cpu(hdr->frame_ctl); 802 fc = le16_to_cpu(hdr->frame_ctl);
795 803
796 if ((fc & IEEE80211_FCTL_VERS) != 0) 804 if ((fc & IEEE80211_FCTL_VERS) != 0)
797 return -EINVAL; 805 goto drop_free;
798 806
799 switch (fc & IEEE80211_FCTL_FTYPE) { 807 switch (fc & IEEE80211_FCTL_FTYPE) {
800 case IEEE80211_FTYPE_MGMT: 808 case IEEE80211_FTYPE_MGMT:
809 if (skb->len < sizeof(struct ieee80211_hdr_3addr))
810 goto drop_free;
801 ieee80211_rx_mgt(ieee, hdr, stats); 811 ieee80211_rx_mgt(ieee, hdr, stats);
802 return 0; 812 dev_kfree_skb_irq(skb);
813 return;
803 case IEEE80211_FTYPE_DATA: 814 case IEEE80211_FTYPE_DATA:
804 break; 815 break;
805 case IEEE80211_FTYPE_CTL: 816 case IEEE80211_FTYPE_CTL:
806 return 0; 817 return;
807 default: 818 default:
808 return -EINVAL; 819 return;
809 } 820 }
810 821
811 is_packet_for_us = 0; 822 is_packet_for_us = 0;
@@ -849,8 +860,14 @@ int ieee80211_rx_any(struct ieee80211_device *ieee,
849 } 860 }
850 861
851 if (is_packet_for_us) 862 if (is_packet_for_us)
852 return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL); 863 if (!ieee80211_rx(ieee, skb, stats))
853 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;
854} 871}
855 872
856#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 873#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
@@ -1061,13 +1078,16 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1061 1078
1062 while (length >= sizeof(*info_element)) { 1079 while (length >= sizeof(*info_element)) {
1063 if (sizeof(*info_element) + info_element->len > length) { 1080 if (sizeof(*info_element) + info_element->len > length) {
1064 IEEE80211_DEBUG_MGMT("Info elem: parse failed: " 1081 IEEE80211_ERROR("Info elem: parse failed: "
1065 "info_element->len + 2 > left : " 1082 "info_element->len + 2 > left : "
1066 "info_element->len+2=%zd left=%d, id=%d.\n", 1083 "info_element->len+2=%zd left=%d, id=%d.\n",
1067 info_element->len + 1084 info_element->len +
1068 sizeof(*info_element), 1085 sizeof(*info_element),
1069 length, info_element->id); 1086 length, info_element->id);
1070 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;
1071 } 1091 }
1072 1092
1073 switch (info_element->id) { 1093 switch (info_element->id) {
@@ -1166,6 +1186,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1166 1186
1167 case MFIE_TYPE_ERP_INFO: 1187 case MFIE_TYPE_ERP_INFO:
1168 network->erp_value = info_element->data[0]; 1188 network->erp_value = info_element->data[0];
1189 network->flags |= NETWORK_HAS_ERP_VALUE;
1169 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", 1190 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1170 network->erp_value); 1191 network->erp_value);
1171 break; 1192 break;
@@ -1729,5 +1750,6 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1729 } 1750 }
1730} 1751}
1731 1752
1753EXPORT_SYMBOL_GPL(ieee80211_rx_any);
1732EXPORT_SYMBOL(ieee80211_rx_mgt); 1754EXPORT_SYMBOL(ieee80211_rx_mgt);
1733EXPORT_SYMBOL(ieee80211_rx); 1755EXPORT_SYMBOL(ieee80211_rx);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index bf042139c7ab..ae254497ba3d 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -337,7 +337,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
337 hdr_len += 2; 337 hdr_len += 2;
338 338
339 skb->priority = ieee80211_classify(skb); 339 skb->priority = ieee80211_classify(skb);
340 header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID; 340 header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID);
341 } 341 }
342 header.frame_ctl = cpu_to_le16(fc); 342 header.frame_ctl = cpu_to_le16(fc);
343 343
@@ -532,13 +532,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
532 return 0; 532 return 0;
533 } 533 }
534 534
535 if (ret == NETDEV_TX_BUSY) {
536 printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
537 "driver should report queue full via "
538 "ieee_device->is_queue_full.\n",
539 ieee->dev->name);
540 }
541
542 ieee80211_txb_free(txb); 535 ieee80211_txb_free(txb);
543 } 536 }
544 537
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 44215ce64d4e..589f6d2c548a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -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}
@@ -334,11 +334,19 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
334 struct ieee80211_assoc_response * resp, 334 struct ieee80211_assoc_response * resp,
335 struct ieee80211softmac_network *net) 335 struct ieee80211softmac_network *net)
336{ 336{
337 u16 cap = le16_to_cpu(resp->capability);
338 u8 erp_value = net->erp_value;
339
337 mac->associnfo.associating = 0; 340 mac->associnfo.associating = 0;
338 mac->associnfo.supported_rates = net->supported_rates; 341 mac->bssinfo.supported_rates = net->supported_rates;
339 ieee80211softmac_recalc_txrates(mac); 342 ieee80211softmac_recalc_txrates(mac);
340 343
341 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
342 if (mac->set_bssid_filter) 350 if (mac->set_bssid_filter)
343 mac->set_bssid_filter(mac->dev, net->bssid); 351 mac->set_bssid_filter(mac->dev, net->bssid);
344 memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN); 352 memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
@@ -351,9 +359,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
351int 359int
352ieee80211softmac_handle_assoc_response(struct net_device * dev, 360ieee80211softmac_handle_assoc_response(struct net_device * dev,
353 struct ieee80211_assoc_response * resp, 361 struct ieee80211_assoc_response * resp,
354 struct ieee80211_network * _ieee80211_network_do_not_use) 362 struct ieee80211_network * _ieee80211_network)
355{ 363{
356 /* NOTE: the network parameter has to be ignored by 364 /* NOTE: the network parameter has to be mostly ignored by
357 * this code because it is the ieee80211's pointer 365 * this code because it is the ieee80211's pointer
358 * to the struct, not ours (we made a copy) 366 * to the struct, not ours (we made a copy)
359 */ 367 */
@@ -385,6 +393,11 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
385 /* 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 */
386 cancel_delayed_work(&mac->associnfo.timeout); 394 cancel_delayed_work(&mac->associnfo.timeout);
387 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
388 switch (status) { 401 switch (status) {
389 case 0: 402 case 0:
390 dprintk(KERN_INFO PFX "associated!\n"); 403 dprintk(KERN_INFO PFX "associated!\n");
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index 6ae5a1dc7956..82bfddbf33a2 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -467,3 +467,17 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
467 kfree(pkt); 467 kfree(pkt);
468 return 0; 468 return 0;
469} 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 */