aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/ethtool.c14
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c23
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c108
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c35
-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
10 files changed, 267 insertions, 111 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 2797e2815418..e0ca04f38cef 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -143,7 +143,7 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
143static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) 143static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr)
144{ 144{
145 struct ethtool_drvinfo info; 145 struct ethtool_drvinfo info;
146 struct ethtool_ops *ops = dev->ethtool_ops; 146 const struct ethtool_ops *ops = dev->ethtool_ops;
147 147
148 if (!ops->get_drvinfo) 148 if (!ops->get_drvinfo)
149 return -EOPNOTSUPP; 149 return -EOPNOTSUPP;
@@ -169,7 +169,7 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr)
169static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 169static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
170{ 170{
171 struct ethtool_regs regs; 171 struct ethtool_regs regs;
172 struct ethtool_ops *ops = dev->ethtool_ops; 172 const struct ethtool_ops *ops = dev->ethtool_ops;
173 void *regbuf; 173 void *regbuf;
174 int reglen, ret; 174 int reglen, ret;
175 175
@@ -282,7 +282,7 @@ static int ethtool_get_link(struct net_device *dev, void __user *useraddr)
282static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) 282static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
283{ 283{
284 struct ethtool_eeprom eeprom; 284 struct ethtool_eeprom eeprom;
285 struct ethtool_ops *ops = dev->ethtool_ops; 285 const struct ethtool_ops *ops = dev->ethtool_ops;
286 u8 *data; 286 u8 *data;
287 int ret; 287 int ret;
288 288
@@ -327,7 +327,7 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
327static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) 327static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
328{ 328{
329 struct ethtool_eeprom eeprom; 329 struct ethtool_eeprom eeprom;
330 struct ethtool_ops *ops = dev->ethtool_ops; 330 const struct ethtool_ops *ops = dev->ethtool_ops;
331 u8 *data; 331 u8 *data;
332 int ret; 332 int ret;
333 333
@@ -640,7 +640,7 @@ static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
640static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 640static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
641{ 641{
642 struct ethtool_test test; 642 struct ethtool_test test;
643 struct ethtool_ops *ops = dev->ethtool_ops; 643 const struct ethtool_ops *ops = dev->ethtool_ops;
644 u64 *data; 644 u64 *data;
645 int ret; 645 int ret;
646 646
@@ -673,7 +673,7 @@ static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
673static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) 673static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
674{ 674{
675 struct ethtool_gstrings gstrings; 675 struct ethtool_gstrings gstrings;
676 struct ethtool_ops *ops = dev->ethtool_ops; 676 const struct ethtool_ops *ops = dev->ethtool_ops;
677 u8 *data; 677 u8 *data;
678 int ret; 678 int ret;
679 679
@@ -733,7 +733,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
733static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) 733static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
734{ 734{
735 struct ethtool_stats stats; 735 struct ethtool_stats stats;
736 struct ethtool_ops *ops = dev->ethtool_ops; 736 const struct ethtool_ops *ops = dev->ethtool_ops;
737 u64 *data; 737 u64 *data;
738 int ret; 738 int ret;
739 739
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index ed90a8af1444..098c66846339 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -271,6 +271,27 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
271 return 0; 271 return 0;
272} 272}
273 273
274/*
275 * deal with seq counter wrapping correctly.
276 * refer to timer_after() for jiffies wrapping handling
277 */
278static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o)
279{
280 u32 iv32_n, iv16_n;
281 u32 iv32_o, iv16_o;
282
283 iv32_n = (pn_n[0] << 24) | (pn_n[1] << 16) | (pn_n[2] << 8) | pn_n[3];
284 iv16_n = (pn_n[4] << 8) | pn_n[5];
285
286 iv32_o = (pn_o[0] << 24) | (pn_o[1] << 16) | (pn_o[2] << 8) | pn_o[3];
287 iv16_o = (pn_o[4] << 8) | pn_o[5];
288
289 if ((s32)iv32_n - (s32)iv32_o < 0 ||
290 (iv32_n == iv32_o && iv16_n <= iv16_o))
291 return 1;
292 return 0;
293}
294
274static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 295static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
275{ 296{
276 struct ieee80211_ccmp_data *key = priv; 297 struct ieee80211_ccmp_data *key = priv;
@@ -323,7 +344,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
323 pn[5] = pos[0]; 344 pn[5] = pos[0];
324 pos += 8; 345 pos += 8;
325 346
326 if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { 347 if (ccmp_replay_check(pn, key->rx_pn)) {
327 if (net_ratelimit()) { 348 if (net_ratelimit()) {
328 printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT 349 printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
329 " previous PN %02x%02x%02x%02x%02x%02x " 350 " 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 34dba0ba545d..f2df2f5b3e4c 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -52,8 +52,10 @@ struct ieee80211_tkip_data {
52 52
53 int key_idx; 53 int key_idx;
54 54
55 struct crypto_tfm *tfm_arc4; 55 struct crypto_tfm *tx_tfm_arc4;
56 struct crypto_tfm *tfm_michael; 56 struct crypto_tfm *tx_tfm_michael;
57 struct crypto_tfm *rx_tfm_arc4;
58 struct crypto_tfm *rx_tfm_michael;
57 59
58 /* scratch buffers for virt_to_page() (crypto API) */ 60 /* scratch buffers for virt_to_page() (crypto API) */
59 u8 rx_hdr[16], tx_hdr[16]; 61 u8 rx_hdr[16], tx_hdr[16];
@@ -85,15 +87,29 @@ static void *ieee80211_tkip_init(int key_idx)
85 87
86 priv->key_idx = key_idx; 88 priv->key_idx = key_idx;
87 89
88 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0); 90 priv->tx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
89 if (priv->tfm_arc4 == NULL) { 91 if (priv->tx_tfm_arc4 == NULL) {
90 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 92 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
91 "crypto API arc4\n"); 93 "crypto API arc4\n");
92 goto fail; 94 goto fail;
93 } 95 }
94 96
95 priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0); 97 priv->tx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
96 if (priv->tfm_michael == NULL) { 98 if (priv->tx_tfm_michael == NULL) {
99 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
100 "crypto API michael_mic\n");
101 goto fail;
102 }
103
104 priv->rx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
105 if (priv->rx_tfm_arc4 == NULL) {
106 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
107 "crypto API arc4\n");
108 goto fail;
109 }
110
111 priv->rx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
112 if (priv->rx_tfm_michael == NULL) {
97 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " 113 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
98 "crypto API michael_mic\n"); 114 "crypto API michael_mic\n");
99 goto fail; 115 goto fail;
@@ -103,10 +119,14 @@ static void *ieee80211_tkip_init(int key_idx)
103 119
104 fail: 120 fail:
105 if (priv) { 121 if (priv) {
106 if (priv->tfm_michael) 122 if (priv->tx_tfm_michael)
107 crypto_free_tfm(priv->tfm_michael); 123 crypto_free_tfm(priv->tx_tfm_michael);
108 if (priv->tfm_arc4) 124 if (priv->tx_tfm_arc4)
109 crypto_free_tfm(priv->tfm_arc4); 125 crypto_free_tfm(priv->tx_tfm_arc4);
126 if (priv->rx_tfm_michael)
127 crypto_free_tfm(priv->rx_tfm_michael);
128 if (priv->rx_tfm_arc4)
129 crypto_free_tfm(priv->rx_tfm_arc4);
110 kfree(priv); 130 kfree(priv);
111 } 131 }
112 132
@@ -116,10 +136,16 @@ static void *ieee80211_tkip_init(int key_idx)
116static void ieee80211_tkip_deinit(void *priv) 136static void ieee80211_tkip_deinit(void *priv)
117{ 137{
118 struct ieee80211_tkip_data *_priv = priv; 138 struct ieee80211_tkip_data *_priv = priv;
119 if (_priv && _priv->tfm_michael) 139 if (_priv) {
120 crypto_free_tfm(_priv->tfm_michael); 140 if (_priv->tx_tfm_michael)
121 if (_priv && _priv->tfm_arc4) 141 crypto_free_tfm(_priv->tx_tfm_michael);
122 crypto_free_tfm(_priv->tfm_arc4); 142 if (_priv->tx_tfm_arc4)
143 crypto_free_tfm(_priv->tx_tfm_arc4);
144 if (_priv->rx_tfm_michael)
145 crypto_free_tfm(_priv->rx_tfm_michael);
146 if (_priv->rx_tfm_arc4)
147 crypto_free_tfm(_priv->rx_tfm_arc4);
148 }
123 kfree(priv); 149 kfree(priv);
124} 150}
125 151
@@ -351,12 +377,25 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
351 icv[2] = crc >> 16; 377 icv[2] = crc >> 16;
352 icv[3] = crc >> 24; 378 icv[3] = crc >> 24;
353 379
354 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); 380 crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
355 sg.page = virt_to_page(pos); 381 sg.page = virt_to_page(pos);
356 sg.offset = offset_in_page(pos); 382 sg.offset = offset_in_page(pos);
357 sg.length = len + 4; 383 sg.length = len + 4;
358 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4); 384 crypto_cipher_encrypt(tkey->tx_tfm_arc4, &sg, &sg, len + 4);
385
386 return 0;
387}
359 388
389/*
390 * deal with seq counter wrapping correctly.
391 * refer to timer_after() for jiffies wrapping handling
392 */
393static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
394 u32 iv32_o, u16 iv16_o)
395{
396 if ((s32)iv32_n - (s32)iv32_o < 0 ||
397 (iv32_n == iv32_o && iv16_n <= iv16_o))
398 return 1;
360 return 0; 399 return 0;
361} 400}
362 401
@@ -414,8 +453,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
414 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); 453 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
415 pos += 8; 454 pos += 8;
416 455
417 if (iv32 < tkey->rx_iv32 || 456 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
418 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
419 if (net_ratelimit()) { 457 if (net_ratelimit()) {
420 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT 458 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
421 " previous TSC %08x%04x received TSC " 459 " previous TSC %08x%04x received TSC "
@@ -434,11 +472,11 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
434 472
435 plen = skb->len - hdr_len - 12; 473 plen = skb->len - hdr_len - 12;
436 474
437 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); 475 crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
438 sg.page = virt_to_page(pos); 476 sg.page = virt_to_page(pos);
439 sg.offset = offset_in_page(pos); 477 sg.offset = offset_in_page(pos);
440 sg.length = plen + 4; 478 sg.length = plen + 4;
441 crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4); 479 crypto_cipher_decrypt(tkey->rx_tfm_arc4, &sg, &sg, plen + 4);
442 480
443 crc = ~crc32_le(~0, pos, plen); 481 crc = ~crc32_le(~0, pos, plen);
444 icv[0] = crc; 482 icv[0] = crc;
@@ -472,12 +510,12 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
472 return keyidx; 510 return keyidx;
473} 511}
474 512
475static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr, 513static int michael_mic(struct crypto_tfm *tfm_michael, u8 * key, u8 * hdr,
476 u8 * data, size_t data_len, u8 * mic) 514 u8 * data, size_t data_len, u8 * mic)
477{ 515{
478 struct scatterlist sg[2]; 516 struct scatterlist sg[2];
479 517
480 if (tkey->tfm_michael == NULL) { 518 if (tfm_michael == NULL) {
481 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); 519 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
482 return -1; 520 return -1;
483 } 521 }
@@ -489,10 +527,10 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
489 sg[1].offset = offset_in_page(data); 527 sg[1].offset = offset_in_page(data);
490 sg[1].length = data_len; 528 sg[1].length = data_len;
491 529
492 crypto_digest_init(tkey->tfm_michael); 530 crypto_digest_init(tfm_michael);
493 crypto_digest_setkey(tkey->tfm_michael, key, 8); 531 crypto_digest_setkey(tfm_michael, key, 8);
494 crypto_digest_update(tkey->tfm_michael, sg, 2); 532 crypto_digest_update(tfm_michael, sg, 2);
495 crypto_digest_final(tkey->tfm_michael, mic); 533 crypto_digest_final(tfm_michael, mic);
496 534
497 return 0; 535 return 0;
498} 536}
@@ -528,7 +566,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
528 if (stype & IEEE80211_STYPE_QOS_DATA) { 566 if (stype & IEEE80211_STYPE_QOS_DATA) {
529 const struct ieee80211_hdr_3addrqos *qoshdr = 567 const struct ieee80211_hdr_3addrqos *qoshdr =
530 (struct ieee80211_hdr_3addrqos *)skb->data; 568 (struct ieee80211_hdr_3addrqos *)skb->data;
531 hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; 569 hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID);
532 } else 570 } else
533 hdr[12] = 0; /* priority */ 571 hdr[12] = 0; /* priority */
534 572
@@ -550,7 +588,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
550 588
551 michael_mic_hdr(skb, tkey->tx_hdr); 589 michael_mic_hdr(skb, tkey->tx_hdr);
552 pos = skb_put(skb, 8); 590 pos = skb_put(skb, 8);
553 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr, 591 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
554 skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) 592 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
555 return -1; 593 return -1;
556 594
@@ -588,7 +626,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
588 return -1; 626 return -1;
589 627
590 michael_mic_hdr(skb, tkey->rx_hdr); 628 michael_mic_hdr(skb, tkey->rx_hdr);
591 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr, 629 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
592 skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) 630 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
593 return -1; 631 return -1;
594 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { 632 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
@@ -618,14 +656,18 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
618{ 656{
619 struct ieee80211_tkip_data *tkey = priv; 657 struct ieee80211_tkip_data *tkey = priv;
620 int keyidx; 658 int keyidx;
621 struct crypto_tfm *tfm = tkey->tfm_michael; 659 struct crypto_tfm *tfm = tkey->tx_tfm_michael;
622 struct crypto_tfm *tfm2 = tkey->tfm_arc4; 660 struct crypto_tfm *tfm2 = tkey->tx_tfm_arc4;
661 struct crypto_tfm *tfm3 = tkey->rx_tfm_michael;
662 struct crypto_tfm *tfm4 = tkey->rx_tfm_arc4;
623 663
624 keyidx = tkey->key_idx; 664 keyidx = tkey->key_idx;
625 memset(tkey, 0, sizeof(*tkey)); 665 memset(tkey, 0, sizeof(*tkey));
626 tkey->key_idx = keyidx; 666 tkey->key_idx = keyidx;
627 tkey->tfm_michael = tfm; 667 tkey->tx_tfm_michael = tfm;
628 tkey->tfm_arc4 = tfm2; 668 tkey->tx_tfm_arc4 = tfm2;
669 tkey->rx_tfm_michael = tfm3;
670 tkey->rx_tfm_arc4 = tfm4;
629 if (len == TKIP_KEY_LEN) { 671 if (len == TKIP_KEY_LEN) {
630 memcpy(tkey->key, key, TKIP_KEY_LEN); 672 memcpy(tkey->key, key, TKIP_KEY_LEN);
631 tkey->key_set = 1; 673 tkey->key_set = 1;
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 0ebf235f6939..b435b28857ed 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -32,7 +32,8 @@ struct prism2_wep_data {
32 u8 key[WEP_KEY_LEN + 1]; 32 u8 key[WEP_KEY_LEN + 1];
33 u8 key_len; 33 u8 key_len;
34 u8 key_idx; 34 u8 key_idx;
35 struct crypto_tfm *tfm; 35 struct crypto_tfm *tx_tfm;
36 struct crypto_tfm *rx_tfm;
36}; 37};
37 38
38static void *prism2_wep_init(int keyidx) 39static void *prism2_wep_init(int keyidx)
@@ -44,13 +45,19 @@ static void *prism2_wep_init(int keyidx)
44 goto fail; 45 goto fail;
45 priv->key_idx = keyidx; 46 priv->key_idx = keyidx;
46 47
47 priv->tfm = crypto_alloc_tfm("arc4", 0); 48 priv->tx_tfm = crypto_alloc_tfm("arc4", 0);
48 if (priv->tfm == NULL) { 49 if (priv->tx_tfm == NULL) {
49 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " 50 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
50 "crypto API arc4\n"); 51 "crypto API arc4\n");
51 goto fail; 52 goto fail;
52 } 53 }
53 54
55 priv->rx_tfm = crypto_alloc_tfm("arc4", 0);
56 if (priv->rx_tfm == NULL) {
57 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
58 "crypto API arc4\n");
59 goto fail;
60 }
54 /* start WEP IV from a random value */ 61 /* start WEP IV from a random value */
55 get_random_bytes(&priv->iv, 4); 62 get_random_bytes(&priv->iv, 4);
56 63
@@ -58,8 +65,10 @@ static void *prism2_wep_init(int keyidx)
58 65
59 fail: 66 fail:
60 if (priv) { 67 if (priv) {
61 if (priv->tfm) 68 if (priv->tx_tfm)
62 crypto_free_tfm(priv->tfm); 69 crypto_free_tfm(priv->tx_tfm);
70 if (priv->rx_tfm)
71 crypto_free_tfm(priv->rx_tfm);
63 kfree(priv); 72 kfree(priv);
64 } 73 }
65 return NULL; 74 return NULL;
@@ -68,8 +77,12 @@ static void *prism2_wep_init(int keyidx)
68static void prism2_wep_deinit(void *priv) 77static void prism2_wep_deinit(void *priv)
69{ 78{
70 struct prism2_wep_data *_priv = priv; 79 struct prism2_wep_data *_priv = priv;
71 if (_priv && _priv->tfm) 80 if (_priv) {
72 crypto_free_tfm(_priv->tfm); 81 if (_priv->tx_tfm)
82 crypto_free_tfm(_priv->tx_tfm);
83 if (_priv->rx_tfm)
84 crypto_free_tfm(_priv->rx_tfm);
85 }
73 kfree(priv); 86 kfree(priv);
74} 87}
75 88
@@ -151,11 +164,11 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
151 icv[2] = crc >> 16; 164 icv[2] = crc >> 16;
152 icv[3] = crc >> 24; 165 icv[3] = crc >> 24;
153 166
154 crypto_cipher_setkey(wep->tfm, key, klen); 167 crypto_cipher_setkey(wep->tx_tfm, key, klen);
155 sg.page = virt_to_page(pos); 168 sg.page = virt_to_page(pos);
156 sg.offset = offset_in_page(pos); 169 sg.offset = offset_in_page(pos);
157 sg.length = len + 4; 170 sg.length = len + 4;
158 crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4); 171 crypto_cipher_encrypt(wep->tx_tfm, &sg, &sg, len + 4);
159 172
160 return 0; 173 return 0;
161} 174}
@@ -194,11 +207,11 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
194 /* Apply RC4 to data and compute CRC32 over decrypted data */ 207 /* Apply RC4 to data and compute CRC32 over decrypted data */
195 plen = skb->len - hdr_len - 8; 208 plen = skb->len - hdr_len - 8;
196 209
197 crypto_cipher_setkey(wep->tfm, key, klen); 210 crypto_cipher_setkey(wep->rx_tfm, key, klen);
198 sg.page = virt_to_page(pos); 211 sg.page = virt_to_page(pos);
199 sg.offset = offset_in_page(pos); 212 sg.offset = offset_in_page(pos);
200 sg.length = plen + 4; 213 sg.length = plen + 4;
201 crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4); 214 crypto_cipher_decrypt(wep->rx_tfm, &sg, &sg, plen + 4);
202 215
203 crc = ~crc32_le(~0, pos, plen); 216 crc = ~crc32_le(~0, pos, plen);
204 icv[0] = crc; 217 icv[0] = crc;
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 */