aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-21 12:08:21 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-21 12:08:21 -0500
commitac58c9059da8886b5e8cde012a80266b18ca146e (patch)
tree40bf486843a2cace6c3a959d73423e50e6aa0c00 /net/ieee80211
parentdf6db302cb236ac3a683d535a3e2073d9f4b2833 (diff)
parentc4a1745aa09fc110afdefea0e5d025043e348bae (diff)
Merge branch 'linus'
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/ieee80211_crypt.c11
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c8
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c56
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c5
-rw-r--r--net/ieee80211/ieee80211_geo.c48
-rw-r--r--net/ieee80211/ieee80211_module.c20
-rw-r--r--net/ieee80211/ieee80211_rx.c167
-rw-r--r--net/ieee80211/ieee80211_tx.c30
-rw-r--r--net/ieee80211/ieee80211_wx.c152
9 files changed, 404 insertions, 93 deletions
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index ecc9bb196abc..cb71d794a7d1 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -18,7 +18,6 @@
18#include <linux/string.h> 18#include <linux/string.h>
19#include <net/ieee80211.h> 19#include <net/ieee80211.h>
20 20
21
22MODULE_AUTHOR("Jouni Malinen"); 21MODULE_AUTHOR("Jouni Malinen");
23MODULE_DESCRIPTION("HostAP crypto"); 22MODULE_DESCRIPTION("HostAP crypto");
24MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
@@ -33,11 +32,11 @@ static DEFINE_SPINLOCK(ieee80211_crypto_lock);
33 32
34void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) 33void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
35{ 34{
36 struct ieee80211_crypt_data *entry, *next; 35 struct ieee80211_crypt_data *entry, *next;
37 unsigned long flags; 36 unsigned long flags;
38 37
39 spin_lock_irqsave(&ieee->lock, flags); 38 spin_lock_irqsave(&ieee->lock, flags);
40 list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) { 39 list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) {
41 if (atomic_read(&entry->refcnt) != 0 && !force) 40 if (atomic_read(&entry->refcnt) != 0 && !force)
42 continue; 41 continue;
43 42
@@ -141,9 +140,9 @@ int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
141 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); 140 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
142 return -EINVAL; 141 return -EINVAL;
143 142
144 found: 143 found:
145 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " 144 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
146 "'%s'\n", ops->name); 145 "'%s'\n", ops->name);
147 list_del(&alg->list); 146 list_del(&alg->list);
148 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); 147 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
149 kfree(alg); 148 kfree(alg);
@@ -163,7 +162,7 @@ struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
163 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); 162 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
164 return NULL; 163 return NULL;
165 164
166 found: 165 found:
167 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); 166 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
168 return alg->ops; 167 return alg->ops;
169} 168}
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 3840d1911f2b..78b2d13e80e3 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -190,7 +190,8 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
190 ieee80211_ccmp_aes_encrypt(tfm, b0, s0); 190 ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
191} 191}
192 192
193static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv) 193static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
194 u8 *aeskey, int keylen, void *priv)
194{ 195{
195 struct ieee80211_ccmp_data *key = priv; 196 struct ieee80211_ccmp_data *key = priv;
196 int i; 197 int i;
@@ -199,6 +200,9 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
199 if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len) 200 if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
200 return -1; 201 return -1;
201 202
203 if (aeskey != NULL && keylen >= CCMP_TK_LEN)
204 memcpy(aeskey, key->key, CCMP_TK_LEN);
205
202 pos = skb_push(skb, CCMP_HDR_LEN); 206 pos = skb_push(skb, CCMP_HDR_LEN);
203 memmove(pos, pos + CCMP_HDR_LEN, hdr_len); 207 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
204 pos += hdr_len; 208 pos += hdr_len;
@@ -238,7 +242,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
238 return -1; 242 return -1;
239 243
240 data_len = skb->len - hdr_len; 244 data_len = skb->len - hdr_len;
241 len = ieee80211_ccmp_hdr(skb, hdr_len, priv); 245 len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
242 if (len < 0) 246 if (len < 0)
243 return -1; 247 return -1;
244 248
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index e0988320efbf..93def94c1b32 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -80,10 +80,9 @@ static void *ieee80211_tkip_init(int key_idx)
80{ 80{
81 struct ieee80211_tkip_data *priv; 81 struct ieee80211_tkip_data *priv;
82 82
83 priv = kmalloc(sizeof(*priv), GFP_ATOMIC); 83 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
84 if (priv == NULL) 84 if (priv == NULL)
85 goto fail; 85 goto fail;
86 memset(priv, 0, sizeof(*priv));
87 86
88 priv->key_idx = key_idx; 87 priv->key_idx = key_idx;
89 88
@@ -271,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
271#endif 270#endif
272} 271}
273 272
274static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv) 273static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
274 u8 * rc4key, int keylen, void *priv)
275{ 275{
276 struct ieee80211_tkip_data *tkey = priv; 276 struct ieee80211_tkip_data *tkey = priv;
277 int len; 277 int len;
278 u8 *rc4key, *pos, *icv; 278 u8 *pos;
279 struct ieee80211_hdr_4addr *hdr; 279 struct ieee80211_hdr_4addr *hdr;
280 u32 crc;
281 280
282 hdr = (struct ieee80211_hdr_4addr *)skb->data; 281 hdr = (struct ieee80211_hdr_4addr *)skb->data;
283 282
284 if (skb_headroom(skb) < 8 || skb->len < hdr_len) 283 if (skb_headroom(skb) < 8 || skb->len < hdr_len)
285 return NULL; 284 return -1;
285
286 if (rc4key == NULL || keylen < 16)
287 return -1;
286 288
287 if (!tkey->tx_phase1_done) { 289 if (!tkey->tx_phase1_done) {
288 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, 290 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
289 tkey->tx_iv32); 291 tkey->tx_iv32);
290 tkey->tx_phase1_done = 1; 292 tkey->tx_phase1_done = 1;
291 } 293 }
292 rc4key = kmalloc(16, GFP_ATOMIC);
293 if (!rc4key)
294 return NULL;
295 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); 294 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
296 295
297 len = skb->len - hdr_len; 296 len = skb->len - hdr_len;
298 pos = skb_push(skb, 8); 297 pos = skb_push(skb, 8);
299 memmove(pos, pos + 8, hdr_len); 298 memmove(pos, pos + 8, hdr_len);
300 pos += hdr_len; 299 pos += hdr_len;
301 icv = skb_put(skb, 4);
302 300
303 *pos++ = *rc4key; 301 *pos++ = *rc4key;
304 *pos++ = *(rc4key + 1); 302 *pos++ = *(rc4key + 1);
@@ -309,28 +307,28 @@ static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
309 *pos++ = (tkey->tx_iv32 >> 16) & 0xff; 307 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
310 *pos++ = (tkey->tx_iv32 >> 24) & 0xff; 308 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
311 309
312 crc = ~crc32_le(~0, pos, len); 310 tkey->tx_iv16++;
313 icv[0] = crc; 311 if (tkey->tx_iv16 == 0) {
314 icv[1] = crc >> 8; 312 tkey->tx_phase1_done = 0;
315 icv[2] = crc >> 16; 313 tkey->tx_iv32++;
316 icv[3] = crc >> 24; 314 }
317 315
318 return rc4key; 316 return 8;
319} 317}
320 318
321static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 319static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
322{ 320{
323 struct ieee80211_tkip_data *tkey = priv; 321 struct ieee80211_tkip_data *tkey = priv;
324 int len; 322 int len;
325 const u8 *rc4key; 323 u8 rc4key[16], *pos, *icv;
326 u8 *pos; 324 u32 crc;
327 struct scatterlist sg; 325 struct scatterlist sg;
328 326
329 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { 327 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
330 if (net_ratelimit()) { 328 if (net_ratelimit()) {
331 struct ieee80211_hdr_4addr *hdr = 329 struct ieee80211_hdr_4addr *hdr =
332 (struct ieee80211_hdr_4addr *)skb->data; 330 (struct ieee80211_hdr_4addr *)skb->data;
333 printk(KERN_DEBUG "TKIP countermeasures: dropped " 331 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
334 "TX packet to " MAC_FMT "\n", 332 "TX packet to " MAC_FMT "\n",
335 MAC_ARG(hdr->addr1)); 333 MAC_ARG(hdr->addr1));
336 } 334 }
@@ -343,22 +341,23 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
343 len = skb->len - hdr_len; 341 len = skb->len - hdr_len;
344 pos = skb->data + hdr_len; 342 pos = skb->data + hdr_len;
345 343
346 rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv); 344 if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
347 if (!rc4key)
348 return -1; 345 return -1;
349 346
347 icv = skb_put(skb, 4);
348
349 crc = ~crc32_le(~0, pos, len);
350 icv[0] = crc;
351 icv[1] = crc >> 8;
352 icv[2] = crc >> 16;
353 icv[3] = crc >> 24;
354
350 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); 355 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
351 sg.page = virt_to_page(pos); 356 sg.page = virt_to_page(pos);
352 sg.offset = offset_in_page(pos); 357 sg.offset = offset_in_page(pos);
353 sg.length = len + 4; 358 sg.length = len + 4;
354 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4); 359 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
355 360
356 tkey->tx_iv16++;
357 if (tkey->tx_iv16 == 0) {
358 tkey->tx_phase1_done = 0;
359 tkey->tx_iv32++;
360 }
361
362 return 0; 361 return 0;
363} 362}
364 363
@@ -379,7 +378,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
379 378
380 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { 379 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
381 if (net_ratelimit()) { 380 if (net_ratelimit()) {
382 printk(KERN_DEBUG "TKIP countermeasures: dropped " 381 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
383 "received packet from " MAC_FMT "\n", 382 "received packet from " MAC_FMT "\n",
384 MAC_ARG(hdr->addr2)); 383 MAC_ARG(hdr->addr2));
385 } 384 }
@@ -695,6 +694,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
695 .name = "TKIP", 694 .name = "TKIP",
696 .init = ieee80211_tkip_init, 695 .init = ieee80211_tkip_init,
697 .deinit = ieee80211_tkip_deinit, 696 .deinit = ieee80211_tkip_deinit,
697 .build_iv = ieee80211_tkip_hdr,
698 .encrypt_mpdu = ieee80211_tkip_encrypt, 698 .encrypt_mpdu = ieee80211_tkip_encrypt,
699 .decrypt_mpdu = ieee80211_tkip_decrypt, 699 .decrypt_mpdu = ieee80211_tkip_decrypt,
700 .encrypt_msdu = ieee80211_michael_mic_add, 700 .encrypt_msdu = ieee80211_michael_mic_add,
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index f8dca31be5dd..649e581fa565 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -76,7 +76,8 @@ static void prism2_wep_deinit(void *priv)
76} 76}
77 77
78/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */ 78/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
79static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv) 79static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
80 u8 *key, int keylen, void *priv)
80{ 81{
81 struct prism2_wep_data *wep = priv; 82 struct prism2_wep_data *wep = priv;
82 u32 klen, len; 83 u32 klen, len;
@@ -131,7 +132,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
131 return -1; 132 return -1;
132 133
133 /* add the IV to the frame */ 134 /* add the IV to the frame */
134 if (prism2_wep_build_iv(skb, hdr_len, priv)) 135 if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))
135 return -1; 136 return -1;
136 137
137 /* Copy the IV into the first 3 bytes of the key */ 138 /* Copy the IV into the first 3 bytes of the key */
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
index 610cc5cbc252..192243ab35ed 100644
--- a/net/ieee80211/ieee80211_geo.c
+++ b/net/ieee80211/ieee80211_geo.c
@@ -50,7 +50,8 @@ int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
50 50
51 /* Driver needs to initialize the geography map before using 51 /* Driver needs to initialize the geography map before using
52 * these helper functions */ 52 * these helper functions */
53 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); 53 if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
54 return 0;
54 55
55 if (ieee->freq_band & IEEE80211_24GHZ_BAND) 56 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
56 for (i = 0; i < ieee->geo.bg_channels; i++) 57 for (i = 0; i < ieee->geo.bg_channels; i++)
@@ -58,13 +59,15 @@ int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
58 * this is a B only channel, we don't see it 59 * this is a B only channel, we don't see it
59 * as valid. */ 60 * as valid. */
60 if ((ieee->geo.bg[i].channel == channel) && 61 if ((ieee->geo.bg[i].channel == channel) &&
62 !(ieee->geo.bg[i].flags & IEEE80211_CH_INVALID) &&
61 (!(ieee->mode & IEEE_G) || 63 (!(ieee->mode & IEEE_G) ||
62 !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY))) 64 !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
63 return IEEE80211_24GHZ_BAND; 65 return IEEE80211_24GHZ_BAND;
64 66
65 if (ieee->freq_band & IEEE80211_52GHZ_BAND) 67 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
66 for (i = 0; i < ieee->geo.a_channels; i++) 68 for (i = 0; i < ieee->geo.a_channels; i++)
67 if (ieee->geo.a[i].channel == channel) 69 if ((ieee->geo.a[i].channel == channel) &&
70 !(ieee->geo.a[i].flags & IEEE80211_CH_INVALID))
68 return IEEE80211_52GHZ_BAND; 71 return IEEE80211_52GHZ_BAND;
69 72
70 return 0; 73 return 0;
@@ -76,7 +79,8 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
76 79
77 /* Driver needs to initialize the geography map before using 80 /* Driver needs to initialize the geography map before using
78 * these helper functions */ 81 * these helper functions */
79 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); 82 if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
83 return -1;
80 84
81 if (ieee->freq_band & IEEE80211_24GHZ_BAND) 85 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
82 for (i = 0; i < ieee->geo.bg_channels; i++) 86 for (i = 0; i < ieee->geo.bg_channels; i++)
@@ -97,7 +101,8 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
97 101
98 /* Driver needs to initialize the geography map before using 102 /* Driver needs to initialize the geography map before using
99 * these helper functions */ 103 * these helper functions */
100 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); 104 if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
105 return 0;
101 106
102 freq /= 100000; 107 freq /= 100000;
103 108
@@ -133,6 +138,41 @@ const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
133 return &ieee->geo; 138 return &ieee->geo;
134} 139}
135 140
141u8 ieee80211_get_channel_flags(struct ieee80211_device * ieee, u8 channel)
142{
143 int index = ieee80211_channel_to_index(ieee, channel);
144
145 if (index == -1)
146 return IEEE80211_CH_INVALID;
147
148 if (channel <= IEEE80211_24GHZ_CHANNELS)
149 return ieee->geo.bg[index].flags;
150
151 return ieee->geo.a[index].flags;
152}
153
154static const struct ieee80211_channel bad_channel = {
155 .channel = 0,
156 .flags = IEEE80211_CH_INVALID,
157 .max_power = 0,
158};
159
160const struct ieee80211_channel *ieee80211_get_channel(struct ieee80211_device
161 *ieee, u8 channel)
162{
163 int index = ieee80211_channel_to_index(ieee, channel);
164
165 if (index == -1)
166 return &bad_channel;
167
168 if (channel <= IEEE80211_24GHZ_CHANNELS)
169 return &ieee->geo.bg[index];
170
171 return &ieee->geo.a[index];
172}
173
174EXPORT_SYMBOL(ieee80211_get_channel);
175EXPORT_SYMBOL(ieee80211_get_channel_flags);
136EXPORT_SYMBOL(ieee80211_is_valid_channel); 176EXPORT_SYMBOL(ieee80211_is_valid_channel);
137EXPORT_SYMBOL(ieee80211_freq_to_channel); 177EXPORT_SYMBOL(ieee80211_freq_to_channel);
138EXPORT_SYMBOL(ieee80211_channel_to_index); 178EXPORT_SYMBOL(ieee80211_channel_to_index);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 90d18b72da3d..2cb84d84f671 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -82,10 +82,28 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
82 return 0; 82 return 0;
83} 83}
84 84
85void ieee80211_network_reset(struct ieee80211_network *network)
86{
87 if (!network)
88 return;
89
90 if (network->ibss_dfs) {
91 kfree(network->ibss_dfs);
92 network->ibss_dfs = NULL;
93 }
94}
95
85static inline void ieee80211_networks_free(struct ieee80211_device *ieee) 96static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
86{ 97{
98 int i;
99
87 if (!ieee->networks) 100 if (!ieee->networks)
88 return; 101 return;
102
103 for (i = 0; i < MAX_NETWORK_COUNT; i++)
104 if (ieee->networks[i].ibss_dfs)
105 kfree(ieee->networks[i].ibss_dfs);
106
89 kfree(ieee->networks); 107 kfree(ieee->networks);
90 ieee->networks = NULL; 108 ieee->networks = NULL;
91} 109}
@@ -195,7 +213,7 @@ void free_ieee80211(struct net_device *dev)
195 213
196static int debug = 0; 214static int debug = 0;
197u32 ieee80211_debug_level = 0; 215u32 ieee80211_debug_level = 0;
198struct proc_dir_entry *ieee80211_proc = NULL; 216static struct proc_dir_entry *ieee80211_proc = NULL;
199 217
200static int show_debug_level(char *page, char **start, off_t offset, 218static int show_debug_level(char *page, char **start, off_t offset,
201 int count, int *eof, void *data) 219 int count, int *eof, void *data)
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 7ac6a7165d9c..a7f2a642a512 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -369,8 +369,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
369 369
370 /* Put this code here so that we avoid duplicating it in all 370 /* Put this code here so that we avoid duplicating it in all
371 * Rx paths. - Jean II */ 371 * Rx paths. - Jean II */
372#ifdef CONFIG_WIRELESS_EXT
372#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ 373#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
373#ifdef CONFIG_NET_RADIO
374 /* If spy monitoring on */ 374 /* If spy monitoring on */
375 if (ieee->spy_data.spy_number > 0) { 375 if (ieee->spy_data.spy_number > 0) {
376 struct iw_quality wstats; 376 struct iw_quality wstats;
@@ -397,8 +397,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
397 /* Update spy records */ 397 /* Update spy records */
398 wireless_spy_update(ieee->dev, hdr->addr2, &wstats); 398 wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
399 } 399 }
400#endif /* CONFIG_NET_RADIO */
401#endif /* IW_WIRELESS_SPY */ 400#endif /* IW_WIRELESS_SPY */
401#endif /* CONFIG_WIRELESS_EXT */
402 402
403#ifdef NOT_YET 403#ifdef NOT_YET
404 hostap_update_rx_stats(local->ap, hdr, rx_stats); 404 hostap_update_rx_stats(local->ap, hdr, rx_stats);
@@ -574,7 +574,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
574 /* skb: hdr + (possibly fragmented) plaintext payload */ 574 /* skb: hdr + (possibly fragmented) plaintext payload */
575 // PR: FIXME: hostap has additional conditions in the "if" below: 575 // PR: FIXME: hostap has additional conditions in the "if" below:
576 // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && 576 // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
577 if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { 577 if ((frag != 0) || (fc & IEEE80211_FCTL_MOREFRAGS)) {
578 int flen; 578 int flen;
579 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); 579 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
580 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); 580 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
@@ -754,7 +754,14 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
754 memset(skb->cb, 0, sizeof(skb->cb)); 754 memset(skb->cb, 0, sizeof(skb->cb));
755 skb->dev = dev; 755 skb->dev = dev;
756 skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ 756 skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
757 netif_rx(skb); 757 if (netif_rx(skb) == NET_RX_DROP) {
758 /* netif_rx always succeeds, but it might drop
759 * the packet. If it drops the packet, we log that
760 * in our stats. */
761 IEEE80211_DEBUG_DROP
762 ("RX: netif_rx dropped the packet\n");
763 stats->rx_dropped++;
764 }
758 } 765 }
759 766
760 rx_exit: 767 rx_exit:
@@ -930,6 +937,45 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
930 return rc; 937 return rc;
931} 938}
932 939
940#ifdef CONFIG_IEEE80211_DEBUG
941#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
942
943static const char *get_info_element_string(u16 id)
944{
945 switch (id) {
946 MFIE_STRING(SSID);
947 MFIE_STRING(RATES);
948 MFIE_STRING(FH_SET);
949 MFIE_STRING(DS_SET);
950 MFIE_STRING(CF_SET);
951 MFIE_STRING(TIM);
952 MFIE_STRING(IBSS_SET);
953 MFIE_STRING(COUNTRY);
954 MFIE_STRING(HOP_PARAMS);
955 MFIE_STRING(HOP_TABLE);
956 MFIE_STRING(REQUEST);
957 MFIE_STRING(CHALLENGE);
958 MFIE_STRING(POWER_CONSTRAINT);
959 MFIE_STRING(POWER_CAPABILITY);
960 MFIE_STRING(TPC_REQUEST);
961 MFIE_STRING(TPC_REPORT);
962 MFIE_STRING(SUPP_CHANNELS);
963 MFIE_STRING(CSA);
964 MFIE_STRING(MEASURE_REQUEST);
965 MFIE_STRING(MEASURE_REPORT);
966 MFIE_STRING(QUIET);
967 MFIE_STRING(IBSS_DFS);
968 MFIE_STRING(ERP_INFO);
969 MFIE_STRING(RSN);
970 MFIE_STRING(RATES_EX);
971 MFIE_STRING(GENERIC);
972 MFIE_STRING(QOS_PARAMETER);
973 default:
974 return "UNKNOWN";
975 }
976}
977#endif
978
933static int ieee80211_parse_info_param(struct ieee80211_info_element 979static int ieee80211_parse_info_param(struct ieee80211_info_element
934 *info_element, u16 length, 980 *info_element, u16 length,
935 struct ieee80211_network *network) 981 struct ieee80211_network *network)
@@ -1040,7 +1086,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1040 break; 1086 break;
1041 1087
1042 case MFIE_TYPE_TIM: 1088 case MFIE_TYPE_TIM:
1043 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n"); 1089 network->tim.tim_count = info_element->data[0];
1090 network->tim.tim_period = info_element->data[1];
1091 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
1044 break; 1092 break;
1045 1093
1046 case MFIE_TYPE_ERP_INFO: 1094 case MFIE_TYPE_ERP_INFO:
@@ -1091,10 +1139,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1091 printk(KERN_ERR 1139 printk(KERN_ERR
1092 "QoS Error need to parse QOS_PARAMETER IE\n"); 1140 "QoS Error need to parse QOS_PARAMETER IE\n");
1093 break; 1141 break;
1142 /* 802.11h */
1143 case MFIE_TYPE_POWER_CONSTRAINT:
1144 network->power_constraint = info_element->data[0];
1145 network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
1146 break;
1147
1148 case MFIE_TYPE_CSA:
1149 network->power_constraint = info_element->data[0];
1150 network->flags |= NETWORK_HAS_CSA;
1151 break;
1152
1153 case MFIE_TYPE_QUIET:
1154 network->quiet.count = info_element->data[0];
1155 network->quiet.period = info_element->data[1];
1156 network->quiet.duration = info_element->data[2];
1157 network->quiet.offset = info_element->data[3];
1158 network->flags |= NETWORK_HAS_QUIET;
1159 break;
1160
1161 case MFIE_TYPE_IBSS_DFS:
1162 if (network->ibss_dfs)
1163 break;
1164 network->ibss_dfs =
1165 kmalloc(info_element->len, GFP_ATOMIC);
1166 if (!network->ibss_dfs)
1167 return 1;
1168 memcpy(network->ibss_dfs, info_element->data,
1169 info_element->len);
1170 network->flags |= NETWORK_HAS_IBSS_DFS;
1171 break;
1172
1173 case MFIE_TYPE_TPC_REPORT:
1174 network->tpc_report.transmit_power =
1175 info_element->data[0];
1176 network->tpc_report.link_margin = info_element->data[1];
1177 network->flags |= NETWORK_HAS_TPC_REPORT;
1178 break;
1094 1179
1095 default: 1180 default:
1096 IEEE80211_DEBUG_MGMT("unsupported IE %d\n", 1181 IEEE80211_DEBUG_MGMT
1097 info_element->id); 1182 ("Unsupported info element: %s (%d)\n",
1183 get_info_element_string(info_element->id),
1184 info_element->id);
1098 break; 1185 break;
1099 } 1186 }
1100 1187
@@ -1110,7 +1197,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1110static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response 1197static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
1111 *frame, struct ieee80211_rx_stats *stats) 1198 *frame, struct ieee80211_rx_stats *stats)
1112{ 1199{
1113 struct ieee80211_network network_resp; 1200 struct ieee80211_network network_resp = {
1201 .ibss_dfs = NULL,
1202 };
1114 struct ieee80211_network *network = &network_resp; 1203 struct ieee80211_network *network = &network_resp;
1115 struct net_device *dev = ieee->dev; 1204 struct net_device *dev = ieee->dev;
1116 1205
@@ -1253,7 +1342,22 @@ static void update_network(struct ieee80211_network *dst,
1253 int qos_active; 1342 int qos_active;
1254 u8 old_param; 1343 u8 old_param;
1255 1344
1256 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); 1345 ieee80211_network_reset(dst);
1346 dst->ibss_dfs = src->ibss_dfs;
1347
1348 /* We only update the statistics if they were created by receiving
1349 * the network information on the actual channel the network is on.
1350 *
1351 * This keeps beacons received on neighbor channels from bringing
1352 * down the signal level of an AP. */
1353 if (dst->channel == src->stats.received_channel)
1354 memcpy(&dst->stats, &src->stats,
1355 sizeof(struct ieee80211_rx_stats));
1356 else
1357 IEEE80211_DEBUG_SCAN("Network " MAC_FMT " info received "
1358 "off channel (%d vs. %d)\n", MAC_ARG(src->bssid),
1359 dst->channel, src->stats.received_channel);
1360
1257 dst->capability = src->capability; 1361 dst->capability = src->capability;
1258 memcpy(dst->rates, src->rates, src->rates_len); 1362 memcpy(dst->rates, src->rates, src->rates_len);
1259 dst->rates_len = src->rates_len; 1363 dst->rates_len = src->rates_len;
@@ -1269,6 +1373,7 @@ static void update_network(struct ieee80211_network *dst,
1269 dst->listen_interval = src->listen_interval; 1373 dst->listen_interval = src->listen_interval;
1270 dst->atim_window = src->atim_window; 1374 dst->atim_window = src->atim_window;
1271 dst->erp_value = src->erp_value; 1375 dst->erp_value = src->erp_value;
1376 dst->tim = src->tim;
1272 1377
1273 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); 1378 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1274 dst->wpa_ie_len = src->wpa_ie_len; 1379 dst->wpa_ie_len = src->wpa_ie_len;
@@ -1313,7 +1418,9 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1313 *stats) 1418 *stats)
1314{ 1419{
1315 struct net_device *dev = ieee->dev; 1420 struct net_device *dev = ieee->dev;
1316 struct ieee80211_network network; 1421 struct ieee80211_network network = {
1422 .ibss_dfs = NULL,
1423 };
1317 struct ieee80211_network *target; 1424 struct ieee80211_network *target;
1318 struct ieee80211_network *oldest = NULL; 1425 struct ieee80211_network *oldest = NULL;
1319#ifdef CONFIG_IEEE80211_DEBUG 1426#ifdef CONFIG_IEEE80211_DEBUG
@@ -1386,6 +1493,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1386 escape_essid(target->ssid, 1493 escape_essid(target->ssid,
1387 target->ssid_len), 1494 target->ssid_len),
1388 MAC_ARG(target->bssid)); 1495 MAC_ARG(target->bssid));
1496 ieee80211_network_reset(target);
1389 } else { 1497 } else {
1390 /* Otherwise just pull from the free list */ 1498 /* Otherwise just pull from the free list */
1391 target = list_entry(ieee->network_free_list.next, 1499 target = list_entry(ieee->network_free_list.next,
@@ -1402,6 +1510,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1402 "BEACON" : "PROBE RESPONSE"); 1510 "BEACON" : "PROBE RESPONSE");
1403#endif 1511#endif
1404 memcpy(target, &network, sizeof(*target)); 1512 memcpy(target, &network, sizeof(*target));
1513 network.ibss_dfs = NULL;
1405 list_add_tail(&target->list, &ieee->network_list); 1514 list_add_tail(&target->list, &ieee->network_list);
1406 } else { 1515 } else {
1407 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", 1516 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
@@ -1411,6 +1520,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1411 is_beacon(beacon->header.frame_ctl) ? 1520 is_beacon(beacon->header.frame_ctl) ?
1412 "BEACON" : "PROBE RESPONSE"); 1521 "BEACON" : "PROBE RESPONSE");
1413 update_network(target, &network); 1522 update_network(target, &network);
1523 network.ibss_dfs = NULL;
1414 } 1524 }
1415 1525
1416 spin_unlock_irqrestore(&ieee->lock, flags); 1526 spin_unlock_irqrestore(&ieee->lock, flags);
@@ -1495,10 +1605,43 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1495 header); 1605 header);
1496 break; 1606 break;
1497 1607
1608 case IEEE80211_STYPE_ACTION:
1609 IEEE80211_DEBUG_MGMT("ACTION\n");
1610 if (ieee->handle_action)
1611 ieee->handle_action(ieee->dev,
1612 (struct ieee80211_action *)
1613 header, stats);
1614 break;
1615
1616 case IEEE80211_STYPE_REASSOC_REQ:
1617 IEEE80211_DEBUG_MGMT("received reassoc (%d)\n",
1618 WLAN_FC_GET_STYPE(le16_to_cpu
1619 (header->frame_ctl)));
1620
1621 IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n",
1622 ieee->dev->name);
1623 if (ieee->handle_reassoc_request != NULL)
1624 ieee->handle_reassoc_request(ieee->dev,
1625 (struct ieee80211_reassoc_request *)
1626 header);
1627 break;
1628
1629 case IEEE80211_STYPE_ASSOC_REQ:
1630 IEEE80211_DEBUG_MGMT("received assoc (%d)\n",
1631 WLAN_FC_GET_STYPE(le16_to_cpu
1632 (header->frame_ctl)));
1633
1634 IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n",
1635 ieee->dev->name);
1636 if (ieee->handle_assoc_request != NULL)
1637 ieee->handle_assoc_request(ieee->dev);
1638 break;
1639
1498 case IEEE80211_STYPE_DEAUTH: 1640 case IEEE80211_STYPE_DEAUTH:
1499 printk("DEAUTH from AP\n"); 1641 IEEE80211_DEBUG_MGMT("DEAUTH\n");
1500 if (ieee->handle_deauth != NULL) 1642 if (ieee->handle_deauth != NULL)
1501 ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *) 1643 ieee->handle_deauth(ieee->dev,
1644 (struct ieee80211_deauth *)
1502 header); 1645 header);
1503 break; 1646 break;
1504 default: 1647 default:
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 8fdd943ebe8e..8b4332f53394 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -56,7 +56,18 @@ Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
56 `--------------------------------------------------| |------' 56 `--------------------------------------------------| |------'
57Total: 28 non-data bytes `----.----' 57Total: 28 non-data bytes `----.----'
58 | 58 |
59 .- 'Frame data' expands to <---------------------------' 59 .- 'Frame data' expands, if WEP enabled, to <----------'
60 |
61 V
62 ,-----------------------.
63Bytes | 4 | 0-2296 | 4 |
64 |-----|-----------|-----|
65Desc. | IV | Encrypted | ICV |
66 | | Packet | |
67 `-----| |-----'
68 `-----.-----'
69 |
70 .- 'Encrypted Packet' expands to
60 | 71 |
61 V 72 V
62 ,---------------------------------------------------. 73 ,---------------------------------------------------.
@@ -65,18 +76,7 @@ Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
65Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | 76Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
66 | DSAP | SSAP | | | | Packet | 77 | DSAP | SSAP | | | | Packet |
67 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | 78 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
68 `-----------------------------------------| | 79 `----------------------------------------------------
69Total: 8 non-data bytes `----.----'
70 |
71 .- 'IP Packet' expands, if WEP enabled, to <--'
72 |
73 V
74 ,-----------------------.
75Bytes | 4 | 0-2296 | 4 |
76 |-----|-----------|-----|
77Desc. | IV | Encrypted | ICV |
78 | | IP Packet | |
79 `-----------------------'
80Total: 8 non-data bytes 80Total: 8 non-data bytes
81 81
82802.3 Ethernet Data Frame 82802.3 Ethernet Data Frame
@@ -470,7 +470,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
470 atomic_inc(&crypt->refcnt); 470 atomic_inc(&crypt->refcnt);
471 if (crypt->ops->build_iv) 471 if (crypt->ops->build_iv)
472 crypt->ops->build_iv(skb_frag, hdr_len, 472 crypt->ops->build_iv(skb_frag, hdr_len,
473 crypt->priv); 473 ieee->sec.keys[ieee->sec.active_key],
474 ieee->sec.key_sizes[ieee->sec.active_key],
475 crypt->priv);
474 atomic_dec(&crypt->refcnt); 476 atomic_dec(&crypt->refcnt);
475 } 477 }
476 478
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index f87c6b89f845..af7f9bbfd18a 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -149,9 +149,7 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
149 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID | 149 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
150 IW_QUAL_LEVEL_INVALID; 150 IW_QUAL_LEVEL_INVALID;
151 iwe.u.qual.qual = 0; 151 iwe.u.qual.qual = 0;
152 iwe.u.qual.level = 0;
153 } else { 152 } else {
154 iwe.u.qual.level = network->stats.rssi;
155 if (ieee->perfect_rssi == ieee->worst_rssi) 153 if (ieee->perfect_rssi == ieee->worst_rssi)
156 iwe.u.qual.qual = 100; 154 iwe.u.qual.qual = 100;
157 else 155 else
@@ -179,6 +177,13 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
179 iwe.u.qual.noise = network->stats.noise; 177 iwe.u.qual.noise = network->stats.noise;
180 } 178 }
181 179
180 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
181 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
182 iwe.u.qual.level = 0;
183 } else {
184 iwe.u.qual.level = network->stats.signal;
185 }
186
182 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); 187 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
183 188
184 iwe.cmd = IWEVCUSTOM; 189 iwe.cmd = IWEVCUSTOM;
@@ -188,33 +193,21 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
188 if (iwe.u.data.length) 193 if (iwe.u.data.length)
189 start = iwe_stream_add_point(start, stop, &iwe, custom); 194 start = iwe_stream_add_point(start, stop, &iwe, custom);
190 195
196 memset(&iwe, 0, sizeof(iwe));
191 if (network->wpa_ie_len) { 197 if (network->wpa_ie_len) {
192 char buf[MAX_WPA_IE_LEN * 2 + 30]; 198 char buf[MAX_WPA_IE_LEN];
193 199 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
194 u8 *p = buf; 200 iwe.cmd = IWEVGENIE;
195 p += sprintf(p, "wpa_ie="); 201 iwe.u.data.length = network->wpa_ie_len;
196 for (i = 0; i < network->wpa_ie_len; i++) {
197 p += sprintf(p, "%02x", network->wpa_ie[i]);
198 }
199
200 memset(&iwe, 0, sizeof(iwe));
201 iwe.cmd = IWEVCUSTOM;
202 iwe.u.data.length = strlen(buf);
203 start = iwe_stream_add_point(start, stop, &iwe, buf); 202 start = iwe_stream_add_point(start, stop, &iwe, buf);
204 } 203 }
205 204
205 memset(&iwe, 0, sizeof(iwe));
206 if (network->rsn_ie_len) { 206 if (network->rsn_ie_len) {
207 char buf[MAX_WPA_IE_LEN * 2 + 30]; 207 char buf[MAX_WPA_IE_LEN];
208 208 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
209 u8 *p = buf; 209 iwe.cmd = IWEVGENIE;
210 p += sprintf(p, "rsn_ie="); 210 iwe.u.data.length = network->rsn_ie_len;
211 for (i = 0; i < network->rsn_ie_len; i++) {
212 p += sprintf(p, "%02x", network->rsn_ie[i]);
213 }
214
215 memset(&iwe, 0, sizeof(iwe));
216 iwe.cmd = IWEVCUSTOM;
217 iwe.u.data.length = strlen(buf);
218 start = iwe_stream_add_point(start, stop, &iwe, buf); 211 start = iwe_stream_add_point(start, stop, &iwe, buf);
219 } 212 }
220 213
@@ -229,6 +222,28 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
229 if (iwe.u.data.length) 222 if (iwe.u.data.length)
230 start = iwe_stream_add_point(start, stop, &iwe, custom); 223 start = iwe_stream_add_point(start, stop, &iwe, custom);
231 224
225 /* Add spectrum management information */
226 iwe.cmd = -1;
227 p = custom;
228 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
229
230 if (ieee80211_get_channel_flags(ieee, network->channel) &
231 IEEE80211_CH_INVALID) {
232 iwe.cmd = IWEVCUSTOM;
233 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
234 }
235
236 if (ieee80211_get_channel_flags(ieee, network->channel) &
237 IEEE80211_CH_RADAR_DETECT) {
238 iwe.cmd = IWEVCUSTOM;
239 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
240 }
241
242 if (iwe.cmd == IWEVCUSTOM) {
243 iwe.u.data.length = p - custom;
244 start = iwe_stream_add_point(start, stop, &iwe, custom);
245 }
246
232 return start; 247 return start;
233} 248}
234 249
@@ -734,9 +749,98 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
734 return 0; 749 return 0;
735} 750}
736 751
752int ieee80211_wx_set_auth(struct net_device *dev,
753 struct iw_request_info *info,
754 union iwreq_data *wrqu,
755 char *extra)
756{
757 struct ieee80211_device *ieee = netdev_priv(dev);
758 unsigned long flags;
759 int err = 0;
760
761 spin_lock_irqsave(&ieee->lock, flags);
762
763 switch (wrqu->param.flags & IW_AUTH_INDEX) {
764 case IW_AUTH_WPA_VERSION:
765 case IW_AUTH_CIPHER_PAIRWISE:
766 case IW_AUTH_CIPHER_GROUP:
767 case IW_AUTH_KEY_MGMT:
768 /*
769 * Host AP driver does not use these parameters and allows
770 * wpa_supplicant to control them internally.
771 */
772 break;
773 case IW_AUTH_TKIP_COUNTERMEASURES:
774 break; /* FIXME */
775 case IW_AUTH_DROP_UNENCRYPTED:
776 ieee->drop_unencrypted = !!wrqu->param.value;
777 break;
778 case IW_AUTH_80211_AUTH_ALG:
779 break; /* FIXME */
780 case IW_AUTH_WPA_ENABLED:
781 ieee->privacy_invoked = ieee->wpa_enabled = !!wrqu->param.value;
782 break;
783 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
784 ieee->ieee802_1x = !!wrqu->param.value;
785 break;
786 case IW_AUTH_PRIVACY_INVOKED:
787 ieee->privacy_invoked = !!wrqu->param.value;
788 break;
789 default:
790 err = -EOPNOTSUPP;
791 break;
792 }
793 spin_unlock_irqrestore(&ieee->lock, flags);
794 return err;
795}
796
797int ieee80211_wx_get_auth(struct net_device *dev,
798 struct iw_request_info *info,
799 union iwreq_data *wrqu,
800 char *extra)
801{
802 struct ieee80211_device *ieee = netdev_priv(dev);
803 unsigned long flags;
804 int err = 0;
805
806 spin_lock_irqsave(&ieee->lock, flags);
807
808 switch (wrqu->param.flags & IW_AUTH_INDEX) {
809 case IW_AUTH_WPA_VERSION:
810 case IW_AUTH_CIPHER_PAIRWISE:
811 case IW_AUTH_CIPHER_GROUP:
812 case IW_AUTH_KEY_MGMT:
813 case IW_AUTH_TKIP_COUNTERMEASURES: /* FIXME */
814 case IW_AUTH_80211_AUTH_ALG: /* FIXME */
815 /*
816 * Host AP driver does not use these parameters and allows
817 * wpa_supplicant to control them internally.
818 */
819 err = -EOPNOTSUPP;
820 break;
821 case IW_AUTH_DROP_UNENCRYPTED:
822 wrqu->param.value = ieee->drop_unencrypted;
823 break;
824 case IW_AUTH_WPA_ENABLED:
825 wrqu->param.value = ieee->wpa_enabled;
826 break;
827 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
828 wrqu->param.value = ieee->ieee802_1x;
829 break;
830 default:
831 err = -EOPNOTSUPP;
832 break;
833 }
834 spin_unlock_irqrestore(&ieee->lock, flags);
835 return err;
836}
837
737EXPORT_SYMBOL(ieee80211_wx_set_encodeext); 838EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
738EXPORT_SYMBOL(ieee80211_wx_get_encodeext); 839EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
739 840
740EXPORT_SYMBOL(ieee80211_wx_get_scan); 841EXPORT_SYMBOL(ieee80211_wx_get_scan);
741EXPORT_SYMBOL(ieee80211_wx_set_encode); 842EXPORT_SYMBOL(ieee80211_wx_set_encode);
742EXPORT_SYMBOL(ieee80211_wx_get_encode); 843EXPORT_SYMBOL(ieee80211_wx_get_encode);
844
845EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth);
846EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth);