aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ieee80211/Makefile3
-rw-r--r--net/ieee80211/ieee80211_crypt.c59
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c75
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c150
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c26
-rw-r--r--net/ieee80211/ieee80211_geo.c141
-rw-r--r--net/ieee80211/ieee80211_module.c65
-rw-r--r--net/ieee80211/ieee80211_rx.c609
-rw-r--r--net/ieee80211/ieee80211_tx.c310
-rw-r--r--net/ieee80211/ieee80211_wx.c369
10 files changed, 1379 insertions, 428 deletions
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
index a6ccac5baea8..f988417121da 100644
--- a/net/ieee80211/Makefile
+++ b/net/ieee80211/Makefile
@@ -7,5 +7,6 @@ ieee80211-objs := \
7 ieee80211_module.o \ 7 ieee80211_module.o \
8 ieee80211_tx.o \ 8 ieee80211_tx.o \
9 ieee80211_rx.o \ 9 ieee80211_rx.o \
10 ieee80211_wx.o 10 ieee80211_wx.o \
11 ieee80211_geo.o
11 12
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index 61a9d92e455b..f3b6aa3be638 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -41,6 +41,12 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
41{ 41{
42 struct list_head *ptr, *n; 42 struct list_head *ptr, *n;
43 struct ieee80211_crypt_data *entry; 43 struct ieee80211_crypt_data *entry;
44 unsigned long flags;
45
46 spin_lock_irqsave(&ieee->lock, flags);
47
48 if (list_empty(&ieee->crypt_deinit_list))
49 goto unlock;
44 50
45 for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; 51 for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
46 ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { 52 ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
@@ -57,6 +63,18 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
57 } 63 }
58 kfree(entry); 64 kfree(entry);
59 } 65 }
66 unlock:
67 spin_unlock_irqrestore(&ieee->lock, flags);
68}
69
70/* After this, crypt_deinit_list won't accept new members */
71void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
72{
73 unsigned long flags;
74
75 spin_lock_irqsave(&ieee->lock, flags);
76 ieee->crypt_quiesced = 1;
77 spin_unlock_irqrestore(&ieee->lock, flags);
60} 78}
61 79
62void ieee80211_crypt_deinit_handler(unsigned long data) 80void ieee80211_crypt_deinit_handler(unsigned long data)
@@ -64,16 +82,16 @@ void ieee80211_crypt_deinit_handler(unsigned long data)
64 struct ieee80211_device *ieee = (struct ieee80211_device *)data; 82 struct ieee80211_device *ieee = (struct ieee80211_device *)data;
65 unsigned long flags; 83 unsigned long flags;
66 84
67 spin_lock_irqsave(&ieee->lock, flags);
68 ieee80211_crypt_deinit_entries(ieee, 0); 85 ieee80211_crypt_deinit_entries(ieee, 0);
69 if (!list_empty(&ieee->crypt_deinit_list)) { 86
87 spin_lock_irqsave(&ieee->lock, flags);
88 if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
70 printk(KERN_DEBUG "%s: entries remaining in delayed crypt " 89 printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
71 "deletion list\n", ieee->dev->name); 90 "deletion list\n", ieee->dev->name);
72 ieee->crypt_deinit_timer.expires = jiffies + HZ; 91 ieee->crypt_deinit_timer.expires = jiffies + HZ;
73 add_timer(&ieee->crypt_deinit_timer); 92 add_timer(&ieee->crypt_deinit_timer);
74 } 93 }
75 spin_unlock_irqrestore(&ieee->lock, flags); 94 spin_unlock_irqrestore(&ieee->lock, flags);
76
77} 95}
78 96
79void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, 97void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
@@ -93,10 +111,12 @@ void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
93 * locking. */ 111 * locking. */
94 112
95 spin_lock_irqsave(&ieee->lock, flags); 113 spin_lock_irqsave(&ieee->lock, flags);
96 list_add(&tmp->list, &ieee->crypt_deinit_list); 114 if (!ieee->crypt_quiesced) {
97 if (!timer_pending(&ieee->crypt_deinit_timer)) { 115 list_add(&tmp->list, &ieee->crypt_deinit_list);
98 ieee->crypt_deinit_timer.expires = jiffies + HZ; 116 if (!timer_pending(&ieee->crypt_deinit_timer)) {
99 add_timer(&ieee->crypt_deinit_timer); 117 ieee->crypt_deinit_timer.expires = jiffies + HZ;
118 add_timer(&ieee->crypt_deinit_timer);
119 }
100 } 120 }
101 spin_unlock_irqrestore(&ieee->lock, flags); 121 spin_unlock_irqrestore(&ieee->lock, flags);
102} 122}
@@ -191,18 +211,18 @@ static void ieee80211_crypt_null_deinit(void *priv)
191} 211}
192 212
193static struct ieee80211_crypto_ops ieee80211_crypt_null = { 213static struct ieee80211_crypto_ops ieee80211_crypt_null = {
194 .name = "NULL", 214 .name = "NULL",
195 .init = ieee80211_crypt_null_init, 215 .init = ieee80211_crypt_null_init,
196 .deinit = ieee80211_crypt_null_deinit, 216 .deinit = ieee80211_crypt_null_deinit,
197 .encrypt_mpdu = NULL, 217 .encrypt_mpdu = NULL,
198 .decrypt_mpdu = NULL, 218 .decrypt_mpdu = NULL,
199 .encrypt_msdu = NULL, 219 .encrypt_msdu = NULL,
200 .decrypt_msdu = NULL, 220 .decrypt_msdu = NULL,
201 .set_key = NULL, 221 .set_key = NULL,
202 .get_key = NULL, 222 .get_key = NULL,
203 .extra_prefix_len = 0, 223 .extra_mpdu_prefix_len = 0,
204 .extra_postfix_len = 0, 224 .extra_mpdu_postfix_len = 0,
205 .owner = THIS_MODULE, 225 .owner = THIS_MODULE,
206}; 226};
207 227
208static int __init ieee80211_crypto_init(void) 228static int __init ieee80211_crypto_init(void)
@@ -249,6 +269,7 @@ static void __exit ieee80211_crypto_deinit(void)
249EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); 269EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
250EXPORT_SYMBOL(ieee80211_crypt_deinit_handler); 270EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
251EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit); 271EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
272EXPORT_SYMBOL(ieee80211_crypt_quiescing);
252 273
253EXPORT_SYMBOL(ieee80211_register_crypto_ops); 274EXPORT_SYMBOL(ieee80211_register_crypto_ops);
254EXPORT_SYMBOL(ieee80211_unregister_crypto_ops); 275EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 8fc13f45971e..05a853c13012 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -119,7 +119,7 @@ static inline void xor_block(u8 * b, u8 * a, size_t len)
119} 119}
120 120
121static void ccmp_init_blocks(struct crypto_tfm *tfm, 121static void ccmp_init_blocks(struct crypto_tfm *tfm,
122 struct ieee80211_hdr *hdr, 122 struct ieee80211_hdr_4addr *hdr,
123 u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) 123 u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
124{ 124{
125 u8 *pos, qc = 0; 125 u8 *pos, qc = 0;
@@ -191,26 +191,18 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
191 ieee80211_ccmp_aes_encrypt(tfm, b0, s0); 191 ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
192} 192}
193 193
194static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 194static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
195{ 195{
196 struct ieee80211_ccmp_data *key = priv; 196 struct ieee80211_ccmp_data *key = priv;
197 int data_len, i, blocks, last, len; 197 int i;
198 u8 *pos, *mic; 198 u8 *pos;
199 struct ieee80211_hdr *hdr;
200 u8 *b0 = key->tx_b0;
201 u8 *b = key->tx_b;
202 u8 *e = key->tx_e;
203 u8 *s0 = key->tx_s0;
204 199
205 if (skb_headroom(skb) < CCMP_HDR_LEN || 200 if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
206 skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
207 return -1; 201 return -1;
208 202
209 data_len = skb->len - hdr_len;
210 pos = skb_push(skb, CCMP_HDR_LEN); 203 pos = skb_push(skb, CCMP_HDR_LEN);
211 memmove(pos, pos + CCMP_HDR_LEN, hdr_len); 204 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
212 pos += hdr_len; 205 pos += hdr_len;
213 mic = skb_put(skb, CCMP_MIC_LEN);
214 206
215 i = CCMP_PN_LEN - 1; 207 i = CCMP_PN_LEN - 1;
216 while (i >= 0) { 208 while (i >= 0) {
@@ -229,7 +221,31 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
229 *pos++ = key->tx_pn[1]; 221 *pos++ = key->tx_pn[1];
230 *pos++ = key->tx_pn[0]; 222 *pos++ = key->tx_pn[0];
231 223
232 hdr = (struct ieee80211_hdr *)skb->data; 224 return CCMP_HDR_LEN;
225}
226
227static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
228{
229 struct ieee80211_ccmp_data *key = priv;
230 int data_len, i, blocks, last, len;
231 u8 *pos, *mic;
232 struct ieee80211_hdr_4addr *hdr;
233 u8 *b0 = key->tx_b0;
234 u8 *b = key->tx_b;
235 u8 *e = key->tx_e;
236 u8 *s0 = key->tx_s0;
237
238 if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
239 return -1;
240
241 data_len = skb->len - hdr_len;
242 len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
243 if (len < 0)
244 return -1;
245
246 pos = skb->data + hdr_len + CCMP_HDR_LEN;
247 mic = skb_put(skb, CCMP_MIC_LEN);
248 hdr = (struct ieee80211_hdr_4addr *)skb->data;
233 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); 249 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
234 250
235 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; 251 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
@@ -258,7 +274,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
258{ 274{
259 struct ieee80211_ccmp_data *key = priv; 275 struct ieee80211_ccmp_data *key = priv;
260 u8 keyidx, *pos; 276 u8 keyidx, *pos;
261 struct ieee80211_hdr *hdr; 277 struct ieee80211_hdr_4addr *hdr;
262 u8 *b0 = key->rx_b0; 278 u8 *b0 = key->rx_b0;
263 u8 *b = key->rx_b; 279 u8 *b = key->rx_b;
264 u8 *a = key->rx_a; 280 u8 *a = key->rx_a;
@@ -272,7 +288,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
272 return -1; 288 return -1;
273 } 289 }
274 290
275 hdr = (struct ieee80211_hdr *)skb->data; 291 hdr = (struct ieee80211_hdr_4addr *)skb->data;
276 pos = skb->data + hdr_len; 292 pos = skb->data + hdr_len;
277 keyidx = pos[3]; 293 keyidx = pos[3];
278 if (!(keyidx & (1 << 5))) { 294 if (!(keyidx & (1 << 5))) {
@@ -426,19 +442,20 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv)
426} 442}
427 443
428static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { 444static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
429 .name = "CCMP", 445 .name = "CCMP",
430 .init = ieee80211_ccmp_init, 446 .init = ieee80211_ccmp_init,
431 .deinit = ieee80211_ccmp_deinit, 447 .deinit = ieee80211_ccmp_deinit,
432 .encrypt_mpdu = ieee80211_ccmp_encrypt, 448 .build_iv = ieee80211_ccmp_hdr,
433 .decrypt_mpdu = ieee80211_ccmp_decrypt, 449 .encrypt_mpdu = ieee80211_ccmp_encrypt,
434 .encrypt_msdu = NULL, 450 .decrypt_mpdu = ieee80211_ccmp_decrypt,
435 .decrypt_msdu = NULL, 451 .encrypt_msdu = NULL,
436 .set_key = ieee80211_ccmp_set_key, 452 .decrypt_msdu = NULL,
437 .get_key = ieee80211_ccmp_get_key, 453 .set_key = ieee80211_ccmp_set_key,
438 .print_stats = ieee80211_ccmp_print_stats, 454 .get_key = ieee80211_ccmp_get_key,
439 .extra_prefix_len = CCMP_HDR_LEN, 455 .print_stats = ieee80211_ccmp_print_stats,
440 .extra_postfix_len = CCMP_MIC_LEN, 456 .extra_mpdu_prefix_len = CCMP_HDR_LEN,
441 .owner = THIS_MODULE, 457 .extra_mpdu_postfix_len = CCMP_MIC_LEN,
458 .owner = THIS_MODULE,
442}; 459};
443 460
444static int __init ieee80211_crypto_ccmp_init(void) 461static int __init ieee80211_crypto_ccmp_init(void)
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index d4f9164be1a1..2e34f29b7956 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -59,8 +59,24 @@ struct ieee80211_tkip_data {
59 59
60 /* scratch buffers for virt_to_page() (crypto API) */ 60 /* scratch buffers for virt_to_page() (crypto API) */
61 u8 rx_hdr[16], tx_hdr[16]; 61 u8 rx_hdr[16], tx_hdr[16];
62
63 unsigned long flags;
62}; 64};
63 65
66static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
67{
68 struct ieee80211_tkip_data *_priv = priv;
69 unsigned long old_flags = _priv->flags;
70 _priv->flags = flags;
71 return old_flags;
72}
73
74static unsigned long ieee80211_tkip_get_flags(void *priv)
75{
76 struct ieee80211_tkip_data *_priv = priv;
77 return _priv->flags;
78}
79
64static void *ieee80211_tkip_init(int key_idx) 80static void *ieee80211_tkip_init(int key_idx)
65{ 81{
66 struct ieee80211_tkip_data *priv; 82 struct ieee80211_tkip_data *priv;
@@ -69,6 +85,7 @@ static void *ieee80211_tkip_init(int key_idx)
69 if (priv == NULL) 85 if (priv == NULL)
70 goto fail; 86 goto fail;
71 memset(priv, 0, sizeof(*priv)); 87 memset(priv, 0, sizeof(*priv));
88
72 priv->key_idx = key_idx; 89 priv->key_idx = key_idx;
73 90
74 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0); 91 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
@@ -255,25 +272,27 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
255#endif 272#endif
256} 273}
257 274
258static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 275static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
259{ 276{
260 struct ieee80211_tkip_data *tkey = priv; 277 struct ieee80211_tkip_data *tkey = priv;
261 int len; 278 int len;
262 u8 rc4key[16], *pos, *icv; 279 u8 *rc4key, *pos, *icv;
263 struct ieee80211_hdr *hdr; 280 struct ieee80211_hdr_4addr *hdr;
264 u32 crc; 281 u32 crc;
265 struct scatterlist sg;
266 282
267 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || 283 hdr = (struct ieee80211_hdr_4addr *)skb->data;
268 skb->len < hdr_len) 284
269 return -1; 285 if (skb_headroom(skb) < 8 || skb->len < hdr_len)
286 return NULL;
270 287
271 hdr = (struct ieee80211_hdr *)skb->data;
272 if (!tkey->tx_phase1_done) { 288 if (!tkey->tx_phase1_done) {
273 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, 289 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
274 tkey->tx_iv32); 290 tkey->tx_iv32);
275 tkey->tx_phase1_done = 1; 291 tkey->tx_phase1_done = 1;
276 } 292 }
293 rc4key = kmalloc(16, GFP_ATOMIC);
294 if (!rc4key)
295 return NULL;
277 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); 296 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
278 297
279 len = skb->len - hdr_len; 298 len = skb->len - hdr_len;
@@ -282,9 +301,9 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
282 pos += hdr_len; 301 pos += hdr_len;
283 icv = skb_put(skb, 4); 302 icv = skb_put(skb, 4);
284 303
285 *pos++ = rc4key[0]; 304 *pos++ = *rc4key;
286 *pos++ = rc4key[1]; 305 *pos++ = *(rc4key + 1);
287 *pos++ = rc4key[2]; 306 *pos++ = *(rc4key + 2);
288 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ; 307 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
289 *pos++ = tkey->tx_iv32 & 0xff; 308 *pos++ = tkey->tx_iv32 & 0xff;
290 *pos++ = (tkey->tx_iv32 >> 8) & 0xff; 309 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
@@ -297,6 +316,38 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
297 icv[2] = crc >> 16; 316 icv[2] = crc >> 16;
298 icv[3] = crc >> 24; 317 icv[3] = crc >> 24;
299 318
319 return rc4key;
320}
321
322static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
323{
324 struct ieee80211_tkip_data *tkey = priv;
325 int len;
326 const u8 *rc4key;
327 u8 *pos;
328 struct scatterlist sg;
329
330 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
331 if (net_ratelimit()) {
332 struct ieee80211_hdr_4addr *hdr =
333 (struct ieee80211_hdr_4addr *)skb->data;
334 printk(KERN_DEBUG "TKIP countermeasures: dropped "
335 "TX packet to " MAC_FMT "\n",
336 MAC_ARG(hdr->addr1));
337 }
338 return -1;
339 }
340
341 if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
342 return -1;
343
344 len = skb->len - hdr_len;
345 pos = skb->data + hdr_len;
346
347 rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
348 if (!rc4key)
349 return -1;
350
300 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); 351 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
301 sg.page = virt_to_page(pos); 352 sg.page = virt_to_page(pos);
302 sg.offset = offset_in_page(pos); 353 sg.offset = offset_in_page(pos);
@@ -319,16 +370,26 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
319 u8 keyidx, *pos; 370 u8 keyidx, *pos;
320 u32 iv32; 371 u32 iv32;
321 u16 iv16; 372 u16 iv16;
322 struct ieee80211_hdr *hdr; 373 struct ieee80211_hdr_4addr *hdr;
323 u8 icv[4]; 374 u8 icv[4];
324 u32 crc; 375 u32 crc;
325 struct scatterlist sg; 376 struct scatterlist sg;
326 int plen; 377 int plen;
327 378
379 hdr = (struct ieee80211_hdr_4addr *)skb->data;
380
381 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
382 if (net_ratelimit()) {
383 printk(KERN_DEBUG "TKIP countermeasures: dropped "
384 "received packet from " MAC_FMT "\n",
385 MAC_ARG(hdr->addr2));
386 }
387 return -1;
388 }
389
328 if (skb->len < hdr_len + 8 + 4) 390 if (skb->len < hdr_len + 8 + 4)
329 return -1; 391 return -1;
330 392
331 hdr = (struct ieee80211_hdr *)skb->data;
332 pos = skb->data + hdr_len; 393 pos = skb->data + hdr_len;
333 keyidx = pos[3]; 394 keyidx = pos[3];
334 if (!(keyidx & (1 << 5))) { 395 if (!(keyidx & (1 << 5))) {
@@ -441,9 +502,9 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
441 502
442static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) 503static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
443{ 504{
444 struct ieee80211_hdr *hdr11; 505 struct ieee80211_hdr_4addr *hdr11;
445 506
446 hdr11 = (struct ieee80211_hdr *)skb->data; 507 hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
447 switch (le16_to_cpu(hdr11->frame_ctl) & 508 switch (le16_to_cpu(hdr11->frame_ctl) &
448 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { 509 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
449 case IEEE80211_FCTL_TODS: 510 case IEEE80211_FCTL_TODS:
@@ -490,9 +551,9 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
490 return 0; 551 return 0;
491} 552}
492 553
493#if WIRELESS_EXT >= 18
494static void ieee80211_michael_mic_failure(struct net_device *dev, 554static void ieee80211_michael_mic_failure(struct net_device *dev,
495 struct ieee80211_hdr *hdr, int keyidx) 555 struct ieee80211_hdr_4addr *hdr,
556 int keyidx)
496{ 557{
497 union iwreq_data wrqu; 558 union iwreq_data wrqu;
498 struct iw_michaelmicfailure ev; 559 struct iw_michaelmicfailure ev;
@@ -510,28 +571,6 @@ static void ieee80211_michael_mic_failure(struct net_device *dev,
510 wrqu.data.length = sizeof(ev); 571 wrqu.data.length = sizeof(ev);
511 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); 572 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
512} 573}
513#elif WIRELESS_EXT >= 15
514static void ieee80211_michael_mic_failure(struct net_device *dev,
515 struct ieee80211_hdr *hdr, int keyidx)
516{
517 union iwreq_data wrqu;
518 char buf[128];
519
520 /* TODO: needed parameters: count, keyid, key type, TSC */
521 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
522 MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
523 MAC_ARG(hdr->addr2));
524 memset(&wrqu, 0, sizeof(wrqu));
525 wrqu.data.length = strlen(buf);
526 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
527}
528#else /* WIRELESS_EXT >= 15 */
529static inline void ieee80211_michael_mic_failure(struct net_device *dev,
530 struct ieee80211_hdr *hdr,
531 int keyidx)
532{
533}
534#endif /* WIRELESS_EXT >= 15 */
535 574
536static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, 575static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
537 int hdr_len, void *priv) 576 int hdr_len, void *priv)
@@ -547,8 +586,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
547 skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) 586 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
548 return -1; 587 return -1;
549 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { 588 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
550 struct ieee80211_hdr *hdr; 589 struct ieee80211_hdr_4addr *hdr;
551 hdr = (struct ieee80211_hdr *)skb->data; 590 hdr = (struct ieee80211_hdr_4addr *)skb->data;
552 printk(KERN_DEBUG "%s: Michael MIC verification failed for " 591 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
553 "MSDU from " MAC_FMT " keyidx=%d\n", 592 "MSDU from " MAC_FMT " keyidx=%d\n",
554 skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2), 593 skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
@@ -654,19 +693,22 @@ static char *ieee80211_tkip_print_stats(char *p, void *priv)
654} 693}
655 694
656static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { 695static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
657 .name = "TKIP", 696 .name = "TKIP",
658 .init = ieee80211_tkip_init, 697 .init = ieee80211_tkip_init,
659 .deinit = ieee80211_tkip_deinit, 698 .deinit = ieee80211_tkip_deinit,
660 .encrypt_mpdu = ieee80211_tkip_encrypt, 699 .encrypt_mpdu = ieee80211_tkip_encrypt,
661 .decrypt_mpdu = ieee80211_tkip_decrypt, 700 .decrypt_mpdu = ieee80211_tkip_decrypt,
662 .encrypt_msdu = ieee80211_michael_mic_add, 701 .encrypt_msdu = ieee80211_michael_mic_add,
663 .decrypt_msdu = ieee80211_michael_mic_verify, 702 .decrypt_msdu = ieee80211_michael_mic_verify,
664 .set_key = ieee80211_tkip_set_key, 703 .set_key = ieee80211_tkip_set_key,
665 .get_key = ieee80211_tkip_get_key, 704 .get_key = ieee80211_tkip_get_key,
666 .print_stats = ieee80211_tkip_print_stats, 705 .print_stats = ieee80211_tkip_print_stats,
667 .extra_prefix_len = 4 + 4, /* IV + ExtIV */ 706 .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
668 .extra_postfix_len = 8 + 4, /* MIC + ICV */ 707 .extra_mpdu_postfix_len = 4, /* ICV */
669 .owner = THIS_MODULE, 708 .extra_msdu_postfix_len = 8, /* MIC */
709 .get_flags = ieee80211_tkip_get_flags,
710 .set_flags = ieee80211_tkip_set_flags,
711 .owner = THIS_MODULE,
670}; 712};
671 713
672static int __init ieee80211_crypto_tkip_init(void) 714static int __init ieee80211_crypto_tkip_init(void)
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index b4d2514a0902..7c08ed2f2628 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -229,19 +229,19 @@ static char *prism2_wep_print_stats(char *p, void *priv)
229} 229}
230 230
231static struct ieee80211_crypto_ops ieee80211_crypt_wep = { 231static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
232 .name = "WEP", 232 .name = "WEP",
233 .init = prism2_wep_init, 233 .init = prism2_wep_init,
234 .deinit = prism2_wep_deinit, 234 .deinit = prism2_wep_deinit,
235 .encrypt_mpdu = prism2_wep_encrypt, 235 .encrypt_mpdu = prism2_wep_encrypt,
236 .decrypt_mpdu = prism2_wep_decrypt, 236 .decrypt_mpdu = prism2_wep_decrypt,
237 .encrypt_msdu = NULL, 237 .encrypt_msdu = NULL,
238 .decrypt_msdu = NULL, 238 .decrypt_msdu = NULL,
239 .set_key = prism2_wep_set_key, 239 .set_key = prism2_wep_set_key,
240 .get_key = prism2_wep_get_key, 240 .get_key = prism2_wep_get_key,
241 .print_stats = prism2_wep_print_stats, 241 .print_stats = prism2_wep_print_stats,
242 .extra_prefix_len = 4, /* IV */ 242 .extra_mpdu_prefix_len = 4, /* IV */
243 .extra_postfix_len = 4, /* ICV */ 243 .extra_mpdu_postfix_len = 4, /* ICV */
244 .owner = THIS_MODULE, 244 .owner = THIS_MODULE,
245}; 245};
246 246
247static int __init ieee80211_crypto_wep_init(void) 247static int __init ieee80211_crypto_wep_init(void)
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
new file mode 100644
index 000000000000..c4b54ef8f6d5
--- /dev/null
+++ b/net/ieee80211/ieee80211_geo.c
@@ -0,0 +1,141 @@
1/******************************************************************************
2
3 Copyright(c) 2005 Intel Corporation. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Contact Information:
22 James P. Ketrenos <ipw2100-admin@linux.intel.com>
23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25******************************************************************************/
26#include <linux/compiler.h>
27#include <linux/config.h>
28#include <linux/errno.h>
29#include <linux/if_arp.h>
30#include <linux/in6.h>
31#include <linux/in.h>
32#include <linux/ip.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/netdevice.h>
36#include <linux/proc_fs.h>
37#include <linux/skbuff.h>
38#include <linux/slab.h>
39#include <linux/tcp.h>
40#include <linux/types.h>
41#include <linux/version.h>
42#include <linux/wireless.h>
43#include <linux/etherdevice.h>
44#include <asm/uaccess.h>
45
46#include <net/ieee80211.h>
47
48int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
49{
50 int i;
51
52 /* Driver needs to initialize the geography map before using
53 * these helper functions */
54 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
55
56 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
57 for (i = 0; i < ieee->geo.bg_channels; i++)
58 /* NOTE: If G mode is currently supported but
59 * this is a B only channel, we don't see it
60 * as valid. */
61 if ((ieee->geo.bg[i].channel == channel) &&
62 (!(ieee->mode & IEEE_G) ||
63 !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
64 return IEEE80211_24GHZ_BAND;
65
66 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
67 for (i = 0; i < ieee->geo.a_channels; i++)
68 if (ieee->geo.a[i].channel == channel)
69 return IEEE80211_52GHZ_BAND;
70
71 return 0;
72}
73
74int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
75{
76 int i;
77
78 /* Driver needs to initialize the geography map before using
79 * these helper functions */
80 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
81
82 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
83 for (i = 0; i < ieee->geo.bg_channels; i++)
84 if (ieee->geo.bg[i].channel == channel)
85 return i;
86
87 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
88 for (i = 0; i < ieee->geo.a_channels; i++)
89 if (ieee->geo.a[i].channel == channel)
90 return i;
91
92 return -1;
93}
94
95u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
96{
97 int i;
98
99 /* Driver needs to initialize the geography map before using
100 * these helper functions */
101 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
102
103 freq /= 100000;
104
105 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
106 for (i = 0; i < ieee->geo.bg_channels; i++)
107 if (ieee->geo.bg[i].freq == freq)
108 return ieee->geo.bg[i].channel;
109
110 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
111 for (i = 0; i < ieee->geo.a_channels; i++)
112 if (ieee->geo.a[i].freq == freq)
113 return ieee->geo.a[i].channel;
114
115 return 0;
116}
117
118int ieee80211_set_geo(struct ieee80211_device *ieee,
119 const struct ieee80211_geo *geo)
120{
121 memcpy(ieee->geo.name, geo->name, 3);
122 ieee->geo.name[3] = '\0';
123 ieee->geo.bg_channels = geo->bg_channels;
124 ieee->geo.a_channels = geo->a_channels;
125 memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
126 sizeof(struct ieee80211_channel));
127 memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
128 sizeof(struct ieee80211_channel));
129 return 0;
130}
131
132const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
133{
134 return &ieee->geo;
135}
136
137EXPORT_SYMBOL(ieee80211_is_valid_channel);
138EXPORT_SYMBOL(ieee80211_freq_to_channel);
139EXPORT_SYMBOL(ieee80211_channel_to_index);
140EXPORT_SYMBOL(ieee80211_set_geo);
141EXPORT_SYMBOL(ieee80211_get_geo);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 6059e9e37123..f66d792cd204 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -1,6 +1,6 @@
1/******************************************************************************* 1/*******************************************************************************
2 2
3 Copyright(c) 2004 Intel Corporation. All rights reserved. 3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
4 4
5 Portions of this file are based on the WEP enablement code provided by the 5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3 6 Host AP project hostap-drivers v0.1.3
@@ -53,12 +53,15 @@
53 53
54#include <net/ieee80211.h> 54#include <net/ieee80211.h>
55 55
56MODULE_DESCRIPTION("802.11 data/management/control stack"); 56#define DRV_DESCRIPTION "802.11 data/management/control stack"
57MODULE_AUTHOR 57#define DRV_NAME "ieee80211"
58 ("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>"); 58#define DRV_VERSION IEEE80211_VERSION
59MODULE_LICENSE("GPL"); 59#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
60 60
61#define DRV_NAME "ieee80211" 61MODULE_VERSION(DRV_VERSION);
62MODULE_DESCRIPTION(DRV_DESCRIPTION);
63MODULE_AUTHOR(DRV_COPYRIGHT);
64MODULE_LICENSE("GPL");
62 65
63static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) 66static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
64{ 67{
@@ -126,26 +129,34 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
126 129
127 /* Default fragmentation threshold is maximum payload size */ 130 /* Default fragmentation threshold is maximum payload size */
128 ieee->fts = DEFAULT_FTS; 131 ieee->fts = DEFAULT_FTS;
132 ieee->rts = DEFAULT_FTS;
129 ieee->scan_age = DEFAULT_MAX_SCAN_AGE; 133 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
130 ieee->open_wep = 1; 134 ieee->open_wep = 1;
131 135
132 /* Default to enabling full open WEP with host based encrypt/decrypt */ 136 /* Default to enabling full open WEP with host based encrypt/decrypt */
133 ieee->host_encrypt = 1; 137 ieee->host_encrypt = 1;
134 ieee->host_decrypt = 1; 138 ieee->host_decrypt = 1;
139 ieee->host_mc_decrypt = 1;
140
141 /* Host fragementation in Open mode. Default is enabled.
142 * Note: host fragmentation is always enabled if host encryption
143 * is enabled. For cards can do hardware encryption, they must do
144 * hardware fragmentation as well. So we don't need a variable
145 * like host_enc_frag. */
146 ieee->host_open_frag = 1;
135 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ 147 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
136 148
137 INIT_LIST_HEAD(&ieee->crypt_deinit_list); 149 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
138 init_timer(&ieee->crypt_deinit_timer); 150 init_timer(&ieee->crypt_deinit_timer);
139 ieee->crypt_deinit_timer.data = (unsigned long)ieee; 151 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
140 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler; 152 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
153 ieee->crypt_quiesced = 0;
141 154
142 spin_lock_init(&ieee->lock); 155 spin_lock_init(&ieee->lock);
143 156
144 ieee->wpa_enabled = 0; 157 ieee->wpa_enabled = 0;
145 ieee->tkip_countermeasures = 0;
146 ieee->drop_unencrypted = 0; 158 ieee->drop_unencrypted = 0;
147 ieee->privacy_invoked = 0; 159 ieee->privacy_invoked = 0;
148 ieee->ieee802_1x = 1;
149 160
150 return dev; 161 return dev;
151 162
@@ -161,6 +172,7 @@ void free_ieee80211(struct net_device *dev)
161 172
162 int i; 173 int i;
163 174
175 ieee80211_crypt_quiescing(ieee);
164 del_timer_sync(&ieee->crypt_deinit_timer); 176 del_timer_sync(&ieee->crypt_deinit_timer);
165 ieee80211_crypt_deinit_entries(ieee, 1); 177 ieee80211_crypt_deinit_entries(ieee, 1);
166 178
@@ -195,38 +207,26 @@ static int show_debug_level(char *page, char **start, off_t offset,
195static int store_debug_level(struct file *file, const char __user * buffer, 207static int store_debug_level(struct file *file, const char __user * buffer,
196 unsigned long count, void *data) 208 unsigned long count, void *data)
197{ 209{
198 char buf[] = "0x00000000"; 210 char buf[] = "0x00000000\n";
199 char *p = (char *)buf; 211 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
200 unsigned long val; 212 unsigned long val;
201 213
202 if (count > sizeof(buf) - 1) 214 if (copy_from_user(buf, buffer, len))
203 count = sizeof(buf) - 1;
204
205 if (copy_from_user(buf, buffer, count))
206 return count; 215 return count;
207 buf[count] = 0; 216 buf[len] = 0;
208 /* 217 if (sscanf(buf, "%li", &val) != 1)
209 * what a FPOS... What, sscanf(buf, "%i", &val) would be too
210 * scary?
211 */
212 if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
213 p++;
214 if (p[0] == 'x' || p[0] == 'X')
215 p++;
216 val = simple_strtoul(p, &p, 16);
217 } else
218 val = simple_strtoul(p, &p, 10);
219 if (p == buf)
220 printk(KERN_INFO DRV_NAME 218 printk(KERN_INFO DRV_NAME
221 ": %s is not in hex or decimal form.\n", buf); 219 ": %s is not in hex or decimal form.\n", buf);
222 else 220 else
223 ieee80211_debug_level = val; 221 ieee80211_debug_level = val;
224 222
225 return strlen(buf); 223 return strnlen(buf, len);
226} 224}
225#endif /* CONFIG_IEEE80211_DEBUG */
227 226
228static int __init ieee80211_init(void) 227static int __init ieee80211_init(void)
229{ 228{
229#ifdef CONFIG_IEEE80211_DEBUG
230 struct proc_dir_entry *e; 230 struct proc_dir_entry *e;
231 231
232 ieee80211_debug_level = debug; 232 ieee80211_debug_level = debug;
@@ -246,26 +246,33 @@ static int __init ieee80211_init(void)
246 e->read_proc = show_debug_level; 246 e->read_proc = show_debug_level;
247 e->write_proc = store_debug_level; 247 e->write_proc = store_debug_level;
248 e->data = NULL; 248 e->data = NULL;
249#endif /* CONFIG_IEEE80211_DEBUG */
250
251 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
252 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
249 253
250 return 0; 254 return 0;
251} 255}
252 256
253static void __exit ieee80211_exit(void) 257static void __exit ieee80211_exit(void)
254{ 258{
259#ifdef CONFIG_IEEE80211_DEBUG
255 if (ieee80211_proc) { 260 if (ieee80211_proc) {
256 remove_proc_entry("debug_level", ieee80211_proc); 261 remove_proc_entry("debug_level", ieee80211_proc);
257 remove_proc_entry(DRV_NAME, proc_net); 262 remove_proc_entry(DRV_NAME, proc_net);
258 ieee80211_proc = NULL; 263 ieee80211_proc = NULL;
259 } 264 }
265#endif /* CONFIG_IEEE80211_DEBUG */
260} 266}
261 267
268#ifdef CONFIG_IEEE80211_DEBUG
262#include <linux/moduleparam.h> 269#include <linux/moduleparam.h>
263module_param(debug, int, 0444); 270module_param(debug, int, 0444);
264MODULE_PARM_DESC(debug, "debug output mask"); 271MODULE_PARM_DESC(debug, "debug output mask");
272#endif /* CONFIG_IEEE80211_DEBUG */
265 273
266module_exit(ieee80211_exit); 274module_exit(ieee80211_exit);
267module_init(ieee80211_init); 275module_init(ieee80211_init);
268#endif
269 276
270const char *escape_essid(const char *essid, u8 essid_len) 277const char *escape_essid(const char *essid, u8 essid_len)
271{ 278{
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index f7dcd854139e..6b005cb0caa0 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -5,7 +5,7 @@
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen 5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi> 6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> 7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Copyright (c) 2004, Intel Corporation 8 * Copyright (c) 2004-2005, Intel Corporation
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -87,7 +87,7 @@ static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct
87 87
88/* Called only as a tasklet (software IRQ) */ 88/* Called only as a tasklet (software IRQ) */
89static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee, 89static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
90 struct ieee80211_hdr *hdr) 90 struct ieee80211_hdr_4addr *hdr)
91{ 91{
92 struct sk_buff *skb = NULL; 92 struct sk_buff *skb = NULL;
93 u16 sc; 93 u16 sc;
@@ -101,7 +101,7 @@ static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
101 if (frag == 0) { 101 if (frag == 0) {
102 /* Reserve enough space to fit maximum frame length */ 102 /* Reserve enough space to fit maximum frame length */
103 skb = dev_alloc_skb(ieee->dev->mtu + 103 skb = dev_alloc_skb(ieee->dev->mtu +
104 sizeof(struct ieee80211_hdr) + 104 sizeof(struct ieee80211_hdr_4addr) +
105 8 /* LLC */ + 105 8 /* LLC */ +
106 2 /* alignment */ + 106 2 /* alignment */ +
107 8 /* WEP */ + ETH_ALEN /* WDS */ ); 107 8 /* WEP */ + ETH_ALEN /* WDS */ );
@@ -138,7 +138,7 @@ static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
138 138
139/* Called only as a tasklet (software IRQ) */ 139/* Called only as a tasklet (software IRQ) */
140static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, 140static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
141 struct ieee80211_hdr *hdr) 141 struct ieee80211_hdr_4addr *hdr)
142{ 142{
143 u16 sc; 143 u16 sc;
144 unsigned int seq; 144 unsigned int seq;
@@ -176,7 +176,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
176 ieee->dev->name); 176 ieee->dev->name);
177 return 0; 177 return 0;
178/* 178/*
179 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *) 179 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
180 skb->data);*/ 180 skb->data);*/
181 } 181 }
182 182
@@ -232,13 +232,13 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
232{ 232{
233 struct net_device *dev = ieee->dev; 233 struct net_device *dev = ieee->dev;
234 u16 fc, ethertype; 234 u16 fc, ethertype;
235 struct ieee80211_hdr *hdr; 235 struct ieee80211_hdr_3addr *hdr;
236 u8 *pos; 236 u8 *pos;
237 237
238 if (skb->len < 24) 238 if (skb->len < 24)
239 return 0; 239 return 0;
240 240
241 hdr = (struct ieee80211_hdr *)skb->data; 241 hdr = (struct ieee80211_hdr_3addr *)skb->data;
242 fc = le16_to_cpu(hdr->frame_ctl); 242 fc = le16_to_cpu(hdr->frame_ctl);
243 243
244 /* check that the frame is unicast frame to us */ 244 /* check that the frame is unicast frame to us */
@@ -271,26 +271,15 @@ static inline int
271ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, 271ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
272 struct ieee80211_crypt_data *crypt) 272 struct ieee80211_crypt_data *crypt)
273{ 273{
274 struct ieee80211_hdr *hdr; 274 struct ieee80211_hdr_3addr *hdr;
275 int res, hdrlen; 275 int res, hdrlen;
276 276
277 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) 277 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
278 return 0; 278 return 0;
279 279
280 hdr = (struct ieee80211_hdr *)skb->data; 280 hdr = (struct ieee80211_hdr_3addr *)skb->data;
281 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); 281 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
282 282
283#ifdef CONFIG_IEEE80211_CRYPT_TKIP
284 if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) {
285 if (net_ratelimit()) {
286 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
287 "received packet from " MAC_FMT "\n",
288 ieee->dev->name, MAC_ARG(hdr->addr2));
289 }
290 return -1;
291 }
292#endif
293
294 atomic_inc(&crypt->refcnt); 283 atomic_inc(&crypt->refcnt);
295 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); 284 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
296 atomic_dec(&crypt->refcnt); 285 atomic_dec(&crypt->refcnt);
@@ -314,13 +303,13 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
314 struct sk_buff *skb, int keyidx, 303 struct sk_buff *skb, int keyidx,
315 struct ieee80211_crypt_data *crypt) 304 struct ieee80211_crypt_data *crypt)
316{ 305{
317 struct ieee80211_hdr *hdr; 306 struct ieee80211_hdr_3addr *hdr;
318 int res, hdrlen; 307 int res, hdrlen;
319 308
320 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) 309 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
321 return 0; 310 return 0;
322 311
323 hdr = (struct ieee80211_hdr *)skb->data; 312 hdr = (struct ieee80211_hdr_3addr *)skb->data;
324 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); 313 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
325 314
326 atomic_inc(&crypt->refcnt); 315 atomic_inc(&crypt->refcnt);
@@ -343,7 +332,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
343 struct ieee80211_rx_stats *rx_stats) 332 struct ieee80211_rx_stats *rx_stats)
344{ 333{
345 struct net_device *dev = ieee->dev; 334 struct net_device *dev = ieee->dev;
346 struct ieee80211_hdr *hdr; 335 struct ieee80211_hdr_4addr *hdr;
347 size_t hdrlen; 336 size_t hdrlen;
348 u16 fc, type, stype, sc; 337 u16 fc, type, stype, sc;
349 struct net_device_stats *stats; 338 struct net_device_stats *stats;
@@ -363,7 +352,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
363 struct ieee80211_crypt_data *crypt = NULL; 352 struct ieee80211_crypt_data *crypt = NULL;
364 int keyidx = 0; 353 int keyidx = 0;
365 354
366 hdr = (struct ieee80211_hdr *)skb->data; 355 hdr = (struct ieee80211_hdr_4addr *)skb->data;
367 stats = &ieee->stats; 356 stats = &ieee->stats;
368 357
369 if (skb->len < 10) { 358 if (skb->len < 10) {
@@ -378,35 +367,50 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
378 frag = WLAN_GET_SEQ_FRAG(sc); 367 frag = WLAN_GET_SEQ_FRAG(sc);
379 hdrlen = ieee80211_get_hdrlen(fc); 368 hdrlen = ieee80211_get_hdrlen(fc);
380 369
381#ifdef NOT_YET
382#if WIRELESS_EXT > 15
383 /* 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
384 * Rx paths. - Jean II */ 371 * Rx paths. - Jean II */
385#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ 372#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
386 /* If spy monitoring on */ 373 /* If spy monitoring on */
387 if (iface->spy_data.spy_number > 0) { 374 if (ieee->spy_data.spy_number > 0) {
388 struct iw_quality wstats; 375 struct iw_quality wstats;
389 wstats.level = rx_stats->signal; 376
390 wstats.noise = rx_stats->noise; 377 wstats.updated = 0;
391 wstats.updated = 6; /* No qual value */ 378 if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
379 wstats.level = rx_stats->rssi;
380 wstats.updated |= IW_QUAL_LEVEL_UPDATED;
381 } else
382 wstats.updated |= IW_QUAL_LEVEL_INVALID;
383
384 if (rx_stats->mask & IEEE80211_STATMASK_NOISE) {
385 wstats.noise = rx_stats->noise;
386 wstats.updated |= IW_QUAL_NOISE_UPDATED;
387 } else
388 wstats.updated |= IW_QUAL_NOISE_INVALID;
389
390 if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) {
391 wstats.qual = rx_stats->signal;
392 wstats.updated |= IW_QUAL_QUAL_UPDATED;
393 } else
394 wstats.updated |= IW_QUAL_QUAL_INVALID;
395
392 /* Update spy records */ 396 /* Update spy records */
393 wireless_spy_update(dev, hdr->addr2, &wstats); 397 wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
394 } 398 }
395#endif /* IW_WIRELESS_SPY */ 399#endif /* IW_WIRELESS_SPY */
396#endif /* WIRELESS_EXT > 15 */ 400
401#ifdef NOT_YET
397 hostap_update_rx_stats(local->ap, hdr, rx_stats); 402 hostap_update_rx_stats(local->ap, hdr, rx_stats);
398#endif 403#endif
399 404
400#if WIRELESS_EXT > 15
401 if (ieee->iw_mode == IW_MODE_MONITOR) { 405 if (ieee->iw_mode == IW_MODE_MONITOR) {
402 ieee80211_monitor_rx(ieee, skb, rx_stats); 406 ieee80211_monitor_rx(ieee, skb, rx_stats);
403 stats->rx_packets++; 407 stats->rx_packets++;
404 stats->rx_bytes += skb->len; 408 stats->rx_bytes += skb->len;
405 return 1; 409 return 1;
406 } 410 }
407#endif
408 411
409 if (ieee->host_decrypt) { 412 if (is_multicast_ether_addr(hdr->addr1) ? ieee->host_mc_decrypt :
413 ieee->host_decrypt) {
410 int idx = 0; 414 int idx = 0;
411 if (skb->len >= hdrlen + 3) 415 if (skb->len >= hdrlen + 3)
412 idx = skb->data[hdrlen + 3] >> 6; 416 idx = skb->data[hdrlen + 3] >> 6;
@@ -531,6 +535,9 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
531 535
532 /* Nullfunc frames may have PS-bit set, so they must be passed to 536 /* Nullfunc frames may have PS-bit set, so they must be passed to
533 * hostap_handle_sta_rx() before being dropped here. */ 537 * hostap_handle_sta_rx() before being dropped here. */
538
539 stype &= ~IEEE80211_STYPE_QOS_DATA;
540
534 if (stype != IEEE80211_STYPE_DATA && 541 if (stype != IEEE80211_STYPE_DATA &&
535 stype != IEEE80211_STYPE_DATA_CFACK && 542 stype != IEEE80211_STYPE_DATA_CFACK &&
536 stype != IEEE80211_STYPE_DATA_CFPOLL && 543 stype != IEEE80211_STYPE_DATA_CFPOLL &&
@@ -549,7 +556,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
549 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) 556 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
550 goto rx_dropped; 557 goto rx_dropped;
551 558
552 hdr = (struct ieee80211_hdr *)skb->data; 559 hdr = (struct ieee80211_hdr_4addr *)skb->data;
553 560
554 /* skb: hdr + (possibly fragmented) plaintext payload */ 561 /* skb: hdr + (possibly fragmented) plaintext payload */
555 // PR: FIXME: hostap has additional conditions in the "if" below: 562 // PR: FIXME: hostap has additional conditions in the "if" below:
@@ -603,7 +610,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
603 /* this was the last fragment and the frame will be 610 /* this was the last fragment and the frame will be
604 * delivered, so remove skb from fragment cache */ 611 * delivered, so remove skb from fragment cache */
605 skb = frag_skb; 612 skb = frag_skb;
606 hdr = (struct ieee80211_hdr *)skb->data; 613 hdr = (struct ieee80211_hdr_4addr *)skb->data;
607 ieee80211_frag_cache_invalidate(ieee, hdr); 614 ieee80211_frag_cache_invalidate(ieee, hdr);
608 } 615 }
609 616
@@ -613,7 +620,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
613 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) 620 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
614 goto rx_dropped; 621 goto rx_dropped;
615 622
616 hdr = (struct ieee80211_hdr *)skb->data; 623 hdr = (struct ieee80211_hdr_4addr *)skb->data;
617 if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) { 624 if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
618 if ( /*ieee->ieee802_1x && */ 625 if ( /*ieee->ieee802_1x && */
619 ieee80211_is_eapol_frame(ieee, skb)) { 626 ieee80211_is_eapol_frame(ieee, skb)) {
@@ -755,69 +762,179 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
755 762
756#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 763#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
757 764
758static inline int ieee80211_is_ofdm_rate(u8 rate) 765static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
766
767/*
768* Make ther structure we read from the beacon packet has
769* the right values
770*/
771static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
772 *info_element, int sub_type)
759{ 773{
760 switch (rate & ~IEEE80211_BASIC_RATE_MASK) { 774
761 case IEEE80211_OFDM_RATE_6MB: 775 if (info_element->qui_subtype != sub_type)
762 case IEEE80211_OFDM_RATE_9MB: 776 return -1;
763 case IEEE80211_OFDM_RATE_12MB: 777 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
764 case IEEE80211_OFDM_RATE_18MB: 778 return -1;
765 case IEEE80211_OFDM_RATE_24MB: 779 if (info_element->qui_type != QOS_OUI_TYPE)
766 case IEEE80211_OFDM_RATE_36MB: 780 return -1;
767 case IEEE80211_OFDM_RATE_48MB: 781 if (info_element->version != QOS_VERSION_1)
768 case IEEE80211_OFDM_RATE_54MB: 782 return -1;
769 return 1; 783
770 }
771 return 0; 784 return 0;
772} 785}
773 786
774static inline int ieee80211_network_init(struct ieee80211_device *ieee, 787/*
775 struct ieee80211_probe_response 788 * Parse a QoS parameter element
776 *beacon, 789 */
777 struct ieee80211_network *network, 790static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
778 struct ieee80211_rx_stats *stats) 791 *element_param, struct ieee80211_info_element
792 *info_element)
779{ 793{
780#ifdef CONFIG_IEEE80211_DEBUG 794 int ret = 0;
781 char rates_str[64]; 795 u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
782 char *p;
783#endif
784 struct ieee80211_info_element *info_element;
785 u16 left;
786 u8 i;
787 796
788 /* Pull out fixed field data */ 797 if ((info_element == NULL) || (element_param == NULL))
789 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); 798 return -1;
790 network->capability = beacon->capability;
791 network->last_scanned = jiffies;
792 network->time_stamp[0] = beacon->time_stamp[0];
793 network->time_stamp[1] = beacon->time_stamp[1];
794 network->beacon_interval = beacon->beacon_interval;
795 /* Where to pull this? beacon->listen_interval; */
796 network->listen_interval = 0x0A;
797 network->rates_len = network->rates_ex_len = 0;
798 network->last_associate = 0;
799 network->ssid_len = 0;
800 network->flags = 0;
801 network->atim_window = 0;
802 799
803 if (stats->freq == IEEE80211_52GHZ_BAND) { 800 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
804 /* for A band (No DS info) */ 801 memcpy(element_param->info_element.qui, info_element->data,
805 network->channel = stats->received_channel; 802 info_element->len);
803 element_param->info_element.elementID = info_element->id;
804 element_param->info_element.length = info_element->len;
806 } else 805 } else
807 network->flags |= NETWORK_HAS_CCK; 806 ret = -1;
807 if (ret == 0)
808 ret = ieee80211_verify_qos_info(&element_param->info_element,
809 QOS_OUI_PARAM_SUB_TYPE);
810 return ret;
811}
808 812
809 network->wpa_ie_len = 0; 813/*
810 network->rsn_ie_len = 0; 814 * Parse a QoS information element
815 */
816static int ieee80211_read_qos_info_element(struct
817 ieee80211_qos_information_element
818 *element_info, struct ieee80211_info_element
819 *info_element)
820{
821 int ret = 0;
822 u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
823
824 if (element_info == NULL)
825 return -1;
826 if (info_element == NULL)
827 return -1;
828
829 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
830 memcpy(element_info->qui, info_element->data,
831 info_element->len);
832 element_info->elementID = info_element->id;
833 element_info->length = info_element->len;
834 } else
835 ret = -1;
836
837 if (ret == 0)
838 ret = ieee80211_verify_qos_info(element_info,
839 QOS_OUI_INFO_SUB_TYPE);
840 return ret;
841}
842
843/*
844 * Write QoS parameters from the ac parameters.
845 */
846static int ieee80211_qos_convert_ac_to_parameters(struct
847 ieee80211_qos_parameter_info
848 *param_elm, struct
849 ieee80211_qos_parameters
850 *qos_param)
851{
852 int rc = 0;
853 int i;
854 struct ieee80211_qos_ac_parameter *ac_params;
855 u32 txop;
856 u8 cw_min;
857 u8 cw_max;
858
859 for (i = 0; i < QOS_QUEUE_NUM; i++) {
860 ac_params = &(param_elm->ac_params_record[i]);
861
862 qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
863 qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
864
865 cw_min = ac_params->ecw_min_max & 0x0F;
866 qos_param->cw_min[i] = (u16) ((1 << cw_min) - 1);
867
868 cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
869 qos_param->cw_max[i] = (u16) ((1 << cw_max) - 1);
870
871 qos_param->flag[i] =
872 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
873
874 txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
875 qos_param->tx_op_limit[i] = (u16) txop;
876 }
877 return rc;
878}
879
880/*
881 * we have a generic data element which it may contain QoS information or
882 * parameters element. check the information element length to decide
883 * which type to read
884 */
885static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
886 *info_element,
887 struct ieee80211_network *network)
888{
889 int rc = 0;
890 struct ieee80211_qos_parameters *qos_param = NULL;
891 struct ieee80211_qos_information_element qos_info_element;
892
893 rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
894
895 if (rc == 0) {
896 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
897 network->flags |= NETWORK_HAS_QOS_INFORMATION;
898 } else {
899 struct ieee80211_qos_parameter_info param_element;
900
901 rc = ieee80211_read_qos_param_element(&param_element,
902 info_element);
903 if (rc == 0) {
904 qos_param = &(network->qos_data.parameters);
905 ieee80211_qos_convert_ac_to_parameters(&param_element,
906 qos_param);
907 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
908 network->qos_data.param_count =
909 param_element.info_element.ac_info & 0x0F;
910 }
911 }
912
913 if (rc == 0) {
914 IEEE80211_DEBUG_QOS("QoS is supported\n");
915 network->qos_data.supported = 1;
916 }
917 return rc;
918}
919
920static int ieee80211_parse_info_param(struct ieee80211_info_element
921 *info_element, u16 length,
922 struct ieee80211_network *network)
923{
924 u8 i;
925#ifdef CONFIG_IEEE80211_DEBUG
926 char rates_str[64];
927 char *p;
928#endif
811 929
812 info_element = &beacon->info_element; 930 while (length >= sizeof(*info_element)) {
813 left = stats->len - ((void *)info_element - (void *)beacon); 931 if (sizeof(*info_element) + info_element->len > length) {
814 while (left >= sizeof(struct ieee80211_info_element_hdr)) { 932 IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
815 if (sizeof(struct ieee80211_info_element_hdr) + 933 "info_element->len + 2 > left : "
816 info_element->len > left) { 934 "info_element->len+2=%zd left=%d, id=%d.\n",
817 IEEE80211_DEBUG_SCAN 935 info_element->len +
818 ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n", 936 sizeof(*info_element),
819 info_element->len + 937 length, info_element->id);
820 sizeof(struct ieee80211_info_element), left);
821 return 1; 938 return 1;
822 } 939 }
823 940
@@ -837,7 +954,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
837 memset(network->ssid + network->ssid_len, 0, 954 memset(network->ssid + network->ssid_len, 0,
838 IW_ESSID_MAX_SIZE - network->ssid_len); 955 IW_ESSID_MAX_SIZE - network->ssid_len);
839 956
840 IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n", 957 IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
841 network->ssid, network->ssid_len); 958 network->ssid, network->ssid_len);
842 break; 959 break;
843 960
@@ -845,15 +962,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
845#ifdef CONFIG_IEEE80211_DEBUG 962#ifdef CONFIG_IEEE80211_DEBUG
846 p = rates_str; 963 p = rates_str;
847#endif 964#endif
848 network->rates_len = 965 network->rates_len = min(info_element->len,
849 min(info_element->len, MAX_RATES_LENGTH); 966 MAX_RATES_LENGTH);
850 for (i = 0; i < network->rates_len; i++) { 967 for (i = 0; i < network->rates_len; i++) {
851 network->rates[i] = info_element->data[i]; 968 network->rates[i] = info_element->data[i];
852#ifdef CONFIG_IEEE80211_DEBUG 969#ifdef CONFIG_IEEE80211_DEBUG
853 p += snprintf(p, 970 p += snprintf(p, sizeof(rates_str) -
854 sizeof(rates_str) - (p - 971 (p - rates_str), "%02X ",
855 rates_str), 972 network->rates[i]);
856 "%02X ", network->rates[i]);
857#endif 973#endif
858 if (ieee80211_is_ofdm_rate 974 if (ieee80211_is_ofdm_rate
859 (info_element->data[i])) { 975 (info_element->data[i])) {
@@ -865,7 +981,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
865 } 981 }
866 } 982 }
867 983
868 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n", 984 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
869 rates_str, network->rates_len); 985 rates_str, network->rates_len);
870 break; 986 break;
871 987
@@ -873,15 +989,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
873#ifdef CONFIG_IEEE80211_DEBUG 989#ifdef CONFIG_IEEE80211_DEBUG
874 p = rates_str; 990 p = rates_str;
875#endif 991#endif
876 network->rates_ex_len = 992 network->rates_ex_len = min(info_element->len,
877 min(info_element->len, MAX_RATES_EX_LENGTH); 993 MAX_RATES_EX_LENGTH);
878 for (i = 0; i < network->rates_ex_len; i++) { 994 for (i = 0; i < network->rates_ex_len; i++) {
879 network->rates_ex[i] = info_element->data[i]; 995 network->rates_ex[i] = info_element->data[i];
880#ifdef CONFIG_IEEE80211_DEBUG 996#ifdef CONFIG_IEEE80211_DEBUG
881 p += snprintf(p, 997 p += snprintf(p, sizeof(rates_str) -
882 sizeof(rates_str) - (p - 998 (p - rates_str), "%02X ",
883 rates_str), 999 network->rates[i]);
884 "%02X ", network->rates[i]);
885#endif 1000#endif
886 if (ieee80211_is_ofdm_rate 1001 if (ieee80211_is_ofdm_rate
887 (info_element->data[i])) { 1002 (info_element->data[i])) {
@@ -893,40 +1008,51 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
893 } 1008 }
894 } 1009 }
895 1010
896 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n", 1011 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
897 rates_str, network->rates_ex_len); 1012 rates_str, network->rates_ex_len);
898 break; 1013 break;
899 1014
900 case MFIE_TYPE_DS_SET: 1015 case MFIE_TYPE_DS_SET:
901 IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n", 1016 IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
902 info_element->data[0]); 1017 info_element->data[0]);
903 if (stats->freq == IEEE80211_24GHZ_BAND) 1018 network->channel = info_element->data[0];
904 network->channel = info_element->data[0];
905 break; 1019 break;
906 1020
907 case MFIE_TYPE_FH_SET: 1021 case MFIE_TYPE_FH_SET:
908 IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n"); 1022 IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
909 break; 1023 break;
910 1024
911 case MFIE_TYPE_CF_SET: 1025 case MFIE_TYPE_CF_SET:
912 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n"); 1026 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
913 break; 1027 break;
914 1028
915 case MFIE_TYPE_TIM: 1029 case MFIE_TYPE_TIM:
916 IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n"); 1030 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
1031 break;
1032
1033 case MFIE_TYPE_ERP_INFO:
1034 network->erp_value = info_element->data[0];
1035 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1036 network->erp_value);
917 break; 1037 break;
918 1038
919 case MFIE_TYPE_IBSS_SET: 1039 case MFIE_TYPE_IBSS_SET:
920 IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n"); 1040 network->atim_window = info_element->data[0];
1041 IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1042 network->atim_window);
921 break; 1043 break;
922 1044
923 case MFIE_TYPE_CHALLENGE: 1045 case MFIE_TYPE_CHALLENGE:
924 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n"); 1046 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
925 break; 1047 break;
926 1048
927 case MFIE_TYPE_GENERIC: 1049 case MFIE_TYPE_GENERIC:
928 IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", 1050 IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
929 info_element->len); 1051 info_element->len);
1052 if (!ieee80211_parse_qos_info_param_IE(info_element,
1053 network))
1054 break;
1055
930 if (info_element->len >= 4 && 1056 if (info_element->len >= 4 &&
931 info_element->data[0] == 0x00 && 1057 info_element->data[0] == 0x00 &&
932 info_element->data[1] == 0x50 && 1058 info_element->data[1] == 0x50 &&
@@ -940,7 +1066,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
940 break; 1066 break;
941 1067
942 case MFIE_TYPE_RSN: 1068 case MFIE_TYPE_RSN:
943 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n", 1069 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
944 info_element->len); 1070 info_element->len);
945 network->rsn_ie_len = min(info_element->len + 2, 1071 network->rsn_ie_len = min(info_element->len + 2,
946 MAX_WPA_IE_LEN); 1072 MAX_WPA_IE_LEN);
@@ -948,18 +1074,127 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
948 network->rsn_ie_len); 1074 network->rsn_ie_len);
949 break; 1075 break;
950 1076
1077 case MFIE_TYPE_QOS_PARAMETER:
1078 printk(KERN_ERR
1079 "QoS Error need to parse QOS_PARAMETER IE\n");
1080 break;
1081
951 default: 1082 default:
952 IEEE80211_DEBUG_SCAN("unsupported IE %d\n", 1083 IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
953 info_element->id); 1084 info_element->id);
954 break; 1085 break;
955 } 1086 }
956 1087
957 left -= sizeof(struct ieee80211_info_element_hdr) + 1088 length -= sizeof(*info_element) + info_element->len;
958 info_element->len; 1089 info_element =
959 info_element = (struct ieee80211_info_element *) 1090 (struct ieee80211_info_element *)&info_element->
960 &info_element->data[info_element->len]; 1091 data[info_element->len];
1092 }
1093
1094 return 0;
1095}
1096
1097static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
1098 *frame, struct ieee80211_rx_stats *stats)
1099{
1100 struct ieee80211_network network_resp;
1101 struct ieee80211_network *network = &network_resp;
1102 struct net_device *dev = ieee->dev;
1103
1104 network->flags = 0;
1105 network->qos_data.active = 0;
1106 network->qos_data.supported = 0;
1107 network->qos_data.param_count = 0;
1108 network->qos_data.old_param_count = 0;
1109
1110 //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
1111 network->atim_window = le16_to_cpu(frame->aid);
1112 network->listen_interval = le16_to_cpu(frame->status);
1113 memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
1114 network->capability = le16_to_cpu(frame->capability);
1115 network->last_scanned = jiffies;
1116 network->rates_len = network->rates_ex_len = 0;
1117 network->last_associate = 0;
1118 network->ssid_len = 0;
1119 network->erp_value =
1120 (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
1121
1122 if (stats->freq == IEEE80211_52GHZ_BAND) {
1123 /* for A band (No DS info) */
1124 network->channel = stats->received_channel;
1125 } else
1126 network->flags |= NETWORK_HAS_CCK;
1127
1128 network->wpa_ie_len = 0;
1129 network->rsn_ie_len = 0;
1130
1131 if (ieee80211_parse_info_param
1132 (frame->info_element, stats->len - sizeof(*frame), network))
1133 return 1;
1134
1135 network->mode = 0;
1136 if (stats->freq == IEEE80211_52GHZ_BAND)
1137 network->mode = IEEE_A;
1138 else {
1139 if (network->flags & NETWORK_HAS_OFDM)
1140 network->mode |= IEEE_G;
1141 if (network->flags & NETWORK_HAS_CCK)
1142 network->mode |= IEEE_B;
961 } 1143 }
962 1144
1145 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1146 network->flags |= NETWORK_EMPTY_ESSID;
1147
1148 memcpy(&network->stats, stats, sizeof(network->stats));
1149
1150 if (ieee->handle_assoc_response != NULL)
1151 ieee->handle_assoc_response(dev, frame, network);
1152
1153 return 0;
1154}
1155
1156/***************************************************/
1157
1158static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
1159 *beacon,
1160 struct ieee80211_network *network,
1161 struct ieee80211_rx_stats *stats)
1162{
1163 network->qos_data.active = 0;
1164 network->qos_data.supported = 0;
1165 network->qos_data.param_count = 0;
1166 network->qos_data.old_param_count = 0;
1167
1168 /* Pull out fixed field data */
1169 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
1170 network->capability = le16_to_cpu(beacon->capability);
1171 network->last_scanned = jiffies;
1172 network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
1173 network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
1174 network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
1175 /* Where to pull this? beacon->listen_interval; */
1176 network->listen_interval = 0x0A;
1177 network->rates_len = network->rates_ex_len = 0;
1178 network->last_associate = 0;
1179 network->ssid_len = 0;
1180 network->flags = 0;
1181 network->atim_window = 0;
1182 network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
1183 0x3 : 0x0;
1184
1185 if (stats->freq == IEEE80211_52GHZ_BAND) {
1186 /* for A band (No DS info) */
1187 network->channel = stats->received_channel;
1188 } else
1189 network->flags |= NETWORK_HAS_CCK;
1190
1191 network->wpa_ie_len = 0;
1192 network->rsn_ie_len = 0;
1193
1194 if (ieee80211_parse_info_param
1195 (beacon->info_element, stats->len - sizeof(*beacon), network))
1196 return 1;
1197
963 network->mode = 0; 1198 network->mode = 0;
964 if (stats->freq == IEEE80211_52GHZ_BAND) 1199 if (stats->freq == IEEE80211_52GHZ_BAND)
965 network->mode = IEEE_A; 1200 network->mode = IEEE_A;
@@ -1002,6 +1237,9 @@ static inline int is_same_network(struct ieee80211_network *src,
1002static inline void update_network(struct ieee80211_network *dst, 1237static inline void update_network(struct ieee80211_network *dst,
1003 struct ieee80211_network *src) 1238 struct ieee80211_network *src)
1004{ 1239{
1240 int qos_active;
1241 u8 old_param;
1242
1005 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); 1243 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1006 dst->capability = src->capability; 1244 dst->capability = src->capability;
1007 memcpy(dst->rates, src->rates, src->rates_len); 1245 memcpy(dst->rates, src->rates, src->rates_len);
@@ -1017,6 +1255,7 @@ static inline void update_network(struct ieee80211_network *dst,
1017 dst->beacon_interval = src->beacon_interval; 1255 dst->beacon_interval = src->beacon_interval;
1018 dst->listen_interval = src->listen_interval; 1256 dst->listen_interval = src->listen_interval;
1019 dst->atim_window = src->atim_window; 1257 dst->atim_window = src->atim_window;
1258 dst->erp_value = src->erp_value;
1020 1259
1021 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); 1260 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1022 dst->wpa_ie_len = src->wpa_ie_len; 1261 dst->wpa_ie_len = src->wpa_ie_len;
@@ -1024,22 +1263,48 @@ static inline void update_network(struct ieee80211_network *dst,
1024 dst->rsn_ie_len = src->rsn_ie_len; 1263 dst->rsn_ie_len = src->rsn_ie_len;
1025 1264
1026 dst->last_scanned = jiffies; 1265 dst->last_scanned = jiffies;
1266 qos_active = src->qos_data.active;
1267 old_param = dst->qos_data.old_param_count;
1268 if (dst->flags & NETWORK_HAS_QOS_MASK)
1269 memcpy(&dst->qos_data, &src->qos_data,
1270 sizeof(struct ieee80211_qos_data));
1271 else {
1272 dst->qos_data.supported = src->qos_data.supported;
1273 dst->qos_data.param_count = src->qos_data.param_count;
1274 }
1275
1276 if (dst->qos_data.supported == 1) {
1277 if (dst->ssid_len)
1278 IEEE80211_DEBUG_QOS
1279 ("QoS the network %s is QoS supported\n",
1280 dst->ssid);
1281 else
1282 IEEE80211_DEBUG_QOS
1283 ("QoS the network is QoS supported\n");
1284 }
1285 dst->qos_data.active = qos_active;
1286 dst->qos_data.old_param_count = old_param;
1287
1027 /* dst->last_associate is not overwritten */ 1288 /* dst->last_associate is not overwritten */
1028} 1289}
1029 1290
1291static inline int is_beacon(int fc)
1292{
1293 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
1294}
1295
1030static inline void ieee80211_process_probe_response(struct ieee80211_device 1296static inline void ieee80211_process_probe_response(struct ieee80211_device
1031 *ieee, 1297 *ieee, struct
1032 struct
1033 ieee80211_probe_response 1298 ieee80211_probe_response
1034 *beacon, 1299 *beacon, struct ieee80211_rx_stats
1035 struct ieee80211_rx_stats
1036 *stats) 1300 *stats)
1037{ 1301{
1302 struct net_device *dev = ieee->dev;
1038 struct ieee80211_network network; 1303 struct ieee80211_network network;
1039 struct ieee80211_network *target; 1304 struct ieee80211_network *target;
1040 struct ieee80211_network *oldest = NULL; 1305 struct ieee80211_network *oldest = NULL;
1041#ifdef CONFIG_IEEE80211_DEBUG 1306#ifdef CONFIG_IEEE80211_DEBUG
1042 struct ieee80211_info_element *info_element = &beacon->info_element; 1307 struct ieee80211_info_element *info_element = beacon->info_element;
1043#endif 1308#endif
1044 unsigned long flags; 1309 unsigned long flags;
1045 1310
@@ -1070,10 +1335,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
1070 escape_essid(info_element->data, 1335 escape_essid(info_element->data,
1071 info_element->len), 1336 info_element->len),
1072 MAC_ARG(beacon->header.addr3), 1337 MAC_ARG(beacon->header.addr3),
1073 WLAN_FC_GET_STYPE(beacon->header. 1338 is_beacon(le16_to_cpu
1074 frame_ctl) == 1339 (beacon->header.
1075 IEEE80211_STYPE_PROBE_RESP ? 1340 frame_ctl)) ?
1076 "PROBE RESPONSE" : "BEACON"); 1341 "BEACON" : "PROBE RESPONSE");
1077 return; 1342 return;
1078 } 1343 }
1079 1344
@@ -1122,10 +1387,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
1122 escape_essid(network.ssid, 1387 escape_essid(network.ssid,
1123 network.ssid_len), 1388 network.ssid_len),
1124 MAC_ARG(network.bssid), 1389 MAC_ARG(network.bssid),
1125 WLAN_FC_GET_STYPE(beacon->header. 1390 is_beacon(le16_to_cpu
1126 frame_ctl) == 1391 (beacon->header.
1127 IEEE80211_STYPE_PROBE_RESP ? 1392 frame_ctl)) ?
1128 "PROBE RESPONSE" : "BEACON"); 1393 "BEACON" : "PROBE RESPONSE");
1129#endif 1394#endif
1130 memcpy(target, &network, sizeof(*target)); 1395 memcpy(target, &network, sizeof(*target));
1131 list_add_tail(&target->list, &ieee->network_list); 1396 list_add_tail(&target->list, &ieee->network_list);
@@ -1134,34 +1399,60 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
1134 escape_essid(target->ssid, 1399 escape_essid(target->ssid,
1135 target->ssid_len), 1400 target->ssid_len),
1136 MAC_ARG(target->bssid), 1401 MAC_ARG(target->bssid),
1137 WLAN_FC_GET_STYPE(beacon->header. 1402 is_beacon(le16_to_cpu
1138 frame_ctl) == 1403 (beacon->header.
1139 IEEE80211_STYPE_PROBE_RESP ? 1404 frame_ctl)) ?
1140 "PROBE RESPONSE" : "BEACON"); 1405 "BEACON" : "PROBE RESPONSE");
1141 update_network(target, &network); 1406 update_network(target, &network);
1142 } 1407 }
1143 1408
1144 spin_unlock_irqrestore(&ieee->lock, flags); 1409 spin_unlock_irqrestore(&ieee->lock, flags);
1410
1411 if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) {
1412 if (ieee->handle_beacon != NULL)
1413 ieee->handle_beacon(dev, beacon, &network);
1414 } else {
1415 if (ieee->handle_probe_response != NULL)
1416 ieee->handle_probe_response(dev, beacon, &network);
1417 }
1145} 1418}
1146 1419
1147void ieee80211_rx_mgt(struct ieee80211_device *ieee, 1420void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1148 struct ieee80211_hdr *header, 1421 struct ieee80211_hdr_4addr *header,
1149 struct ieee80211_rx_stats *stats) 1422 struct ieee80211_rx_stats *stats)
1150{ 1423{
1151 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { 1424 switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
1152 case IEEE80211_STYPE_ASSOC_RESP: 1425 case IEEE80211_STYPE_ASSOC_RESP:
1153 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n", 1426 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
1154 WLAN_FC_GET_STYPE(header->frame_ctl)); 1427 WLAN_FC_GET_STYPE(le16_to_cpu
1428 (header->frame_ctl)));
1429 ieee80211_handle_assoc_resp(ieee,
1430 (struct ieee80211_assoc_response *)
1431 header, stats);
1155 break; 1432 break;
1156 1433
1157 case IEEE80211_STYPE_REASSOC_RESP: 1434 case IEEE80211_STYPE_REASSOC_RESP:
1158 IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n", 1435 IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
1159 WLAN_FC_GET_STYPE(header->frame_ctl)); 1436 WLAN_FC_GET_STYPE(le16_to_cpu
1437 (header->frame_ctl)));
1438 break;
1439
1440 case IEEE80211_STYPE_PROBE_REQ:
1441 IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
1442 WLAN_FC_GET_STYPE(le16_to_cpu
1443 (header->frame_ctl)));
1444
1445 if (ieee->handle_probe_request != NULL)
1446 ieee->handle_probe_request(ieee->dev,
1447 (struct
1448 ieee80211_probe_request *)
1449 header, stats);
1160 break; 1450 break;
1161 1451
1162 case IEEE80211_STYPE_PROBE_RESP: 1452 case IEEE80211_STYPE_PROBE_RESP:
1163 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", 1453 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1164 WLAN_FC_GET_STYPE(header->frame_ctl)); 1454 WLAN_FC_GET_STYPE(le16_to_cpu
1455 (header->frame_ctl)));
1165 IEEE80211_DEBUG_SCAN("Probe response\n"); 1456 IEEE80211_DEBUG_SCAN("Probe response\n");
1166 ieee80211_process_probe_response(ieee, 1457 ieee80211_process_probe_response(ieee,
1167 (struct 1458 (struct
@@ -1171,20 +1462,46 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1171 1462
1172 case IEEE80211_STYPE_BEACON: 1463 case IEEE80211_STYPE_BEACON:
1173 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", 1464 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1174 WLAN_FC_GET_STYPE(header->frame_ctl)); 1465 WLAN_FC_GET_STYPE(le16_to_cpu
1466 (header->frame_ctl)));
1175 IEEE80211_DEBUG_SCAN("Beacon\n"); 1467 IEEE80211_DEBUG_SCAN("Beacon\n");
1176 ieee80211_process_probe_response(ieee, 1468 ieee80211_process_probe_response(ieee,
1177 (struct 1469 (struct
1178 ieee80211_probe_response *) 1470 ieee80211_probe_response *)
1179 header, stats); 1471 header, stats);
1180 break; 1472 break;
1473 case IEEE80211_STYPE_AUTH:
1181 1474
1475 IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
1476 WLAN_FC_GET_STYPE(le16_to_cpu
1477 (header->frame_ctl)));
1478
1479 if (ieee->handle_auth != NULL)
1480 ieee->handle_auth(ieee->dev,
1481 (struct ieee80211_auth *)header);
1482 break;
1483
1484 case IEEE80211_STYPE_DISASSOC:
1485 if (ieee->handle_disassoc != NULL)
1486 ieee->handle_disassoc(ieee->dev,
1487 (struct ieee80211_disassoc *)
1488 header);
1489 break;
1490
1491 case IEEE80211_STYPE_DEAUTH:
1492 printk("DEAUTH from AP\n");
1493 if (ieee->handle_deauth != NULL)
1494 ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
1495 header);
1496 break;
1182 default: 1497 default:
1183 IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", 1498 IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
1184 WLAN_FC_GET_STYPE(header->frame_ctl)); 1499 WLAN_FC_GET_STYPE(le16_to_cpu
1500 (header->frame_ctl)));
1185 IEEE80211_WARNING("%s: Unknown management packet: %d\n", 1501 IEEE80211_WARNING("%s: Unknown management packet: %d\n",
1186 ieee->dev->name, 1502 ieee->dev->name,
1187 WLAN_FC_GET_STYPE(header->frame_ctl)); 1503 WLAN_FC_GET_STYPE(le16_to_cpu
1504 (header->frame_ctl)));
1188 break; 1505 break;
1189 } 1506 }
1190} 1507}
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index eed07bbbe6b6..42c50619aa8e 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 2
3 Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. 3 Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
4 4
5 This program is free software; you can redistribute it and/or modify it 5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as 6 under the terms of version 2 of the GNU General Public License as
@@ -128,7 +128,7 @@ payload of each frame is reduced to 492 bytes.
128static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; 128static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
129static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; 129static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
130 130
131static inline int ieee80211_put_snap(u8 * data, u16 h_proto) 131static inline int ieee80211_copy_snap(u8 * data, u16 h_proto)
132{ 132{
133 struct ieee80211_snap_hdr *snap; 133 struct ieee80211_snap_hdr *snap;
134 u8 *oui; 134 u8 *oui;
@@ -157,31 +157,11 @@ static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
157 struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; 157 struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
158 int res; 158 int res;
159 159
160#ifdef CONFIG_IEEE80211_CRYPT_TKIP
161 struct ieee80211_hdr *header;
162
163 if (ieee->tkip_countermeasures &&
164 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
165 header = (struct ieee80211_hdr *)frag->data;
166 if (net_ratelimit()) {
167 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
168 "TX packet to " MAC_FMT "\n",
169 ieee->dev->name, MAC_ARG(header->addr1));
170 }
171 return -1;
172 }
173#endif
174 /* To encrypt, frame format is: 160 /* To encrypt, frame format is:
175 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ 161 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
176
177 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
178 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
179 * call both MSDU and MPDU encryption functions from here. */
180 atomic_inc(&crypt->refcnt); 162 atomic_inc(&crypt->refcnt);
181 res = 0; 163 res = 0;
182 if (crypt->ops->encrypt_msdu) 164 if (crypt->ops->encrypt_mpdu)
183 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
184 if (res == 0 && crypt->ops->encrypt_mpdu)
185 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); 165 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
186 166
187 atomic_dec(&crypt->refcnt); 167 atomic_dec(&crypt->refcnt);
@@ -236,25 +216,31 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
236 return txb; 216 return txb;
237} 217}
238 218
239/* SKBs are added to the ieee->tx_queue. */ 219/* Incoming skb is converted to a txb which consists of
220 * a block of 802.11 fragment packets (stored as skbs) */
240int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) 221int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
241{ 222{
242 struct ieee80211_device *ieee = netdev_priv(dev); 223 struct ieee80211_device *ieee = netdev_priv(dev);
243 struct ieee80211_txb *txb = NULL; 224 struct ieee80211_txb *txb = NULL;
244 struct ieee80211_hdr *frag_hdr; 225 struct ieee80211_hdr_3addr *frag_hdr;
245 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; 226 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
227 rts_required;
246 unsigned long flags; 228 unsigned long flags;
247 struct net_device_stats *stats = &ieee->stats; 229 struct net_device_stats *stats = &ieee->stats;
248 int ether_type, encrypt; 230 int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
249 int bytes, fc, hdr_len; 231 int bytes, fc, hdr_len;
250 struct sk_buff *skb_frag; 232 struct sk_buff *skb_frag;
251 struct ieee80211_hdr header = { /* Ensure zero initialized */ 233 struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */
252 .duration_id = 0, 234 .duration_id = 0,
253 .seq_ctl = 0 235 .seq_ctl = 0
254 }; 236 };
255 u8 dest[ETH_ALEN], src[ETH_ALEN]; 237 u8 dest[ETH_ALEN], src[ETH_ALEN];
256
257 struct ieee80211_crypt_data *crypt; 238 struct ieee80211_crypt_data *crypt;
239 int priority = skb->priority;
240 int snapped = 0;
241
242 if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
243 return NETDEV_TX_BUSY;
258 244
259 spin_lock_irqsave(&ieee->lock, flags); 245 spin_lock_irqsave(&ieee->lock, flags);
260 246
@@ -276,7 +262,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
276 crypt = ieee->crypt[ieee->tx_keyidx]; 262 crypt = ieee->crypt[ieee->tx_keyidx];
277 263
278 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && 264 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
279 ieee->host_encrypt && crypt && crypt->ops; 265 ieee->sec.encrypt;
266
267 host_encrypt = ieee->host_encrypt && encrypt;
268 host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;
269 host_build_iv = ieee->host_build_iv && encrypt;
280 270
281 if (!encrypt && ieee->ieee802_1x && 271 if (!encrypt && ieee->ieee802_1x &&
282 ieee->drop_unencrypted && ether_type != ETH_P_PAE) { 272 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
@@ -285,8 +275,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
285 } 275 }
286 276
287 /* Save source and destination addresses */ 277 /* Save source and destination addresses */
288 memcpy(&dest, skb->data, ETH_ALEN); 278 memcpy(dest, skb->data, ETH_ALEN);
289 memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN); 279 memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
290 280
291 /* Advance the SKB to the start of the payload */ 281 /* Advance the SKB to the start of the payload */
292 skb_pull(skb, sizeof(struct ethhdr)); 282 skb_pull(skb, sizeof(struct ethhdr));
@@ -294,7 +284,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
294 /* Determine total amount of storage required for TXB packets */ 284 /* Determine total amount of storage required for TXB packets */
295 bytes = skb->len + SNAP_SIZE + sizeof(u16); 285 bytes = skb->len + SNAP_SIZE + sizeof(u16);
296 286
297 if (encrypt) 287 if (host_encrypt)
298 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | 288 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
299 IEEE80211_FCTL_PROTECTED; 289 IEEE80211_FCTL_PROTECTED;
300 else 290 else
@@ -302,50 +292,90 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
302 292
303 if (ieee->iw_mode == IW_MODE_INFRA) { 293 if (ieee->iw_mode == IW_MODE_INFRA) {
304 fc |= IEEE80211_FCTL_TODS; 294 fc |= IEEE80211_FCTL_TODS;
305 /* To DS: Addr1 = BSSID, Addr2 = SA, 295 /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
306 Addr3 = DA */ 296 memcpy(header.addr1, ieee->bssid, ETH_ALEN);
307 memcpy(&header.addr1, ieee->bssid, ETH_ALEN); 297 memcpy(header.addr2, src, ETH_ALEN);
308 memcpy(&header.addr2, &src, ETH_ALEN); 298 memcpy(header.addr3, dest, ETH_ALEN);
309 memcpy(&header.addr3, &dest, ETH_ALEN);
310 } else if (ieee->iw_mode == IW_MODE_ADHOC) { 299 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
311 /* not From/To DS: Addr1 = DA, Addr2 = SA, 300 /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
312 Addr3 = BSSID */ 301 memcpy(header.addr1, dest, ETH_ALEN);
313 memcpy(&header.addr1, dest, ETH_ALEN); 302 memcpy(header.addr2, src, ETH_ALEN);
314 memcpy(&header.addr2, src, ETH_ALEN); 303 memcpy(header.addr3, ieee->bssid, ETH_ALEN);
315 memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
316 } 304 }
317 header.frame_ctl = cpu_to_le16(fc); 305 header.frame_ctl = cpu_to_le16(fc);
318 hdr_len = IEEE80211_3ADDR_LEN; 306 hdr_len = IEEE80211_3ADDR_LEN;
319 307
320 /* Determine fragmentation size based on destination (multicast 308 /* Encrypt msdu first on the whole data packet. */
321 * and broadcast are not fragmented) */ 309 if ((host_encrypt || host_encrypt_msdu) &&
322 if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest)) 310 crypt && crypt->ops && crypt->ops->encrypt_msdu) {
323 frag_size = MAX_FRAG_THRESHOLD; 311 int res = 0;
324 else 312 int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
325 frag_size = ieee->fts; 313 crypt->ops->extra_msdu_postfix_len;
314 struct sk_buff *skb_new = dev_alloc_skb(len);
315
316 if (unlikely(!skb_new))
317 goto failed;
318
319 skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
320 memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
321 snapped = 1;
322 ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
323 ether_type);
324 memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);
325 res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
326 if (res < 0) {
327 IEEE80211_ERROR("msdu encryption failed\n");
328 dev_kfree_skb_any(skb_new);
329 goto failed;
330 }
331 dev_kfree_skb_any(skb);
332 skb = skb_new;
333 bytes += crypt->ops->extra_msdu_prefix_len +
334 crypt->ops->extra_msdu_postfix_len;
335 skb_pull(skb, hdr_len);
336 }
326 337
327 /* Determine amount of payload per fragment. Regardless of if 338 if (host_encrypt || ieee->host_open_frag) {
328 * this stack is providing the full 802.11 header, one will 339 /* Determine fragmentation size based on destination (multicast
329 * eventually be affixed to this fragment -- so we must account for 340 * and broadcast are not fragmented) */
330 * it when determining the amount of payload space. */ 341 if (is_multicast_ether_addr(dest))
331 bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; 342 frag_size = MAX_FRAG_THRESHOLD;
332 if (ieee->config & 343 else
333 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) 344 frag_size = ieee->fts;
334 bytes_per_frag -= IEEE80211_FCS_LEN; 345
335 346 /* Determine amount of payload per fragment. Regardless of if
336 /* Each fragment may need to have room for encryptiong pre/postfix */ 347 * this stack is providing the full 802.11 header, one will
337 if (encrypt) 348 * eventually be affixed to this fragment -- so we must account
338 bytes_per_frag -= crypt->ops->extra_prefix_len + 349 * for it when determining the amount of payload space. */
339 crypt->ops->extra_postfix_len; 350 bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
340 351 if (ieee->config &
341 /* Number of fragments is the total bytes_per_frag / 352 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
342 * payload_per_fragment */ 353 bytes_per_frag -= IEEE80211_FCS_LEN;
343 nr_frags = bytes / bytes_per_frag; 354
344 bytes_last_frag = bytes % bytes_per_frag; 355 /* Each fragment may need to have room for encryptiong
345 if (bytes_last_frag) 356 * pre/postfix */
357 if (host_encrypt)
358 bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
359 crypt->ops->extra_mpdu_postfix_len;
360
361 /* Number of fragments is the total
362 * bytes_per_frag / payload_per_fragment */
363 nr_frags = bytes / bytes_per_frag;
364 bytes_last_frag = bytes % bytes_per_frag;
365 if (bytes_last_frag)
366 nr_frags++;
367 else
368 bytes_last_frag = bytes_per_frag;
369 } else {
370 nr_frags = 1;
371 bytes_per_frag = bytes_last_frag = bytes;
372 frag_size = bytes + IEEE80211_3ADDR_LEN;
373 }
374
375 rts_required = (frag_size > ieee->rts
376 && ieee->config & CFG_IEEE80211_RTS);
377 if (rts_required)
346 nr_frags++; 378 nr_frags++;
347 else
348 bytes_last_frag = bytes_per_frag;
349 379
350 /* When we allocate the TXB we allocate enough space for the reserve 380 /* When we allocate the TXB we allocate enough space for the reserve
351 * and full fragment bytes (bytes_per_frag doesn't include prefix, 381 * and full fragment bytes (bytes_per_frag doesn't include prefix,
@@ -357,15 +387,47 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
357 goto failed; 387 goto failed;
358 } 388 }
359 txb->encrypted = encrypt; 389 txb->encrypted = encrypt;
360 txb->payload_size = bytes; 390 if (host_encrypt)
391 txb->payload_size = frag_size * (nr_frags - 1) +
392 bytes_last_frag;
393 else
394 txb->payload_size = bytes;
395
396 if (rts_required) {
397 skb_frag = txb->fragments[0];
398 frag_hdr =
399 (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
400
401 /*
402 * Set header frame_ctl to the RTS.
403 */
404 header.frame_ctl =
405 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
406 memcpy(frag_hdr, &header, hdr_len);
361 407
362 for (i = 0; i < nr_frags; i++) { 408 /*
409 * Restore header frame_ctl to the original data setting.
410 */
411 header.frame_ctl = cpu_to_le16(fc);
412
413 if (ieee->config &
414 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
415 skb_put(skb_frag, 4);
416
417 txb->rts_included = 1;
418 i = 1;
419 } else
420 i = 0;
421
422 for (; i < nr_frags; i++) {
363 skb_frag = txb->fragments[i]; 423 skb_frag = txb->fragments[i];
364 424
365 if (encrypt) 425 if (host_encrypt || host_build_iv)
366 skb_reserve(skb_frag, crypt->ops->extra_prefix_len); 426 skb_reserve(skb_frag,
427 crypt->ops->extra_mpdu_prefix_len);
367 428
368 frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len); 429 frag_hdr =
430 (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
369 memcpy(frag_hdr, &header, hdr_len); 431 memcpy(frag_hdr, &header, hdr_len);
370 432
371 /* If this is not the last fragment, then add the MOREFRAGS 433 /* If this is not the last fragment, then add the MOREFRAGS
@@ -379,11 +441,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
379 bytes = bytes_last_frag; 441 bytes = bytes_last_frag;
380 } 442 }
381 443
382 /* Put a SNAP header on the first fragment */ 444 if (i == 0 && !snapped) {
383 if (i == 0) { 445 ieee80211_copy_snap(skb_put
384 ieee80211_put_snap(skb_put 446 (skb_frag, SNAP_SIZE + sizeof(u16)),
385 (skb_frag, SNAP_SIZE + sizeof(u16)), 447 ether_type);
386 ether_type);
387 bytes -= SNAP_SIZE + sizeof(u16); 448 bytes -= SNAP_SIZE + sizeof(u16);
388 } 449 }
389 450
@@ -394,8 +455,19 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
394 455
395 /* Encryption routine will move the header forward in order 456 /* Encryption routine will move the header forward in order
396 * to insert the IV between the header and the payload */ 457 * to insert the IV between the header and the payload */
397 if (encrypt) 458 if (host_encrypt)
398 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); 459 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
460 else if (host_build_iv) {
461 struct ieee80211_crypt_data *crypt;
462
463 crypt = ieee->crypt[ieee->tx_keyidx];
464 atomic_inc(&crypt->refcnt);
465 if (crypt->ops->build_iv)
466 crypt->ops->build_iv(skb_frag, hdr_len,
467 crypt->priv);
468 atomic_dec(&crypt->refcnt);
469 }
470
399 if (ieee->config & 471 if (ieee->config &
400 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) 472 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
401 skb_put(skb_frag, 4); 473 skb_put(skb_frag, 4);
@@ -407,11 +479,20 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
407 dev_kfree_skb_any(skb); 479 dev_kfree_skb_any(skb);
408 480
409 if (txb) { 481 if (txb) {
410 if ((*ieee->hard_start_xmit) (txb, dev) == 0) { 482 int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
483 if (ret == 0) {
411 stats->tx_packets++; 484 stats->tx_packets++;
412 stats->tx_bytes += txb->payload_size; 485 stats->tx_bytes += txb->payload_size;
413 return 0; 486 return 0;
414 } 487 }
488
489 if (ret == NETDEV_TX_BUSY) {
490 printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
491 "driver should report queue full via "
492 "ieee_device->is_queue_full.\n",
493 ieee->dev->name);
494 }
495
415 ieee80211_txb_free(txb); 496 ieee80211_txb_free(txb);
416 } 497 }
417 498
@@ -422,7 +503,72 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
422 netif_stop_queue(dev); 503 netif_stop_queue(dev);
423 stats->tx_errors++; 504 stats->tx_errors++;
424 return 1; 505 return 1;
506}
507
508/* Incoming 802.11 strucure is converted to a TXB
509 * a block of 802.11 fragment packets (stored as skbs) */
510int ieee80211_tx_frame(struct ieee80211_device *ieee,
511 struct ieee80211_hdr *frame, int len)
512{
513 struct ieee80211_txb *txb = NULL;
514 unsigned long flags;
515 struct net_device_stats *stats = &ieee->stats;
516 struct sk_buff *skb_frag;
517 int priority = -1;
518
519 spin_lock_irqsave(&ieee->lock, flags);
425 520
521 /* If there is no driver handler to take the TXB, dont' bother
522 * creating it... */
523 if (!ieee->hard_start_xmit) {
524 printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
525 goto success;
526 }
527
528 if (unlikely(len < 24)) {
529 printk(KERN_WARNING "%s: skb too small (%d).\n",
530 ieee->dev->name, len);
531 goto success;
532 }
533
534 /* When we allocate the TXB we allocate enough space for the reserve
535 * and full fragment bytes (bytes_per_frag doesn't include prefix,
536 * postfix, header, FCS, etc.) */
537 txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC);
538 if (unlikely(!txb)) {
539 printk(KERN_WARNING "%s: Could not allocate TXB\n",
540 ieee->dev->name);
541 goto failed;
542 }
543 txb->encrypted = 0;
544 txb->payload_size = len;
545
546 skb_frag = txb->fragments[0];
547
548 memcpy(skb_put(skb_frag, len), frame, len);
549
550 if (ieee->config &
551 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
552 skb_put(skb_frag, 4);
553
554 success:
555 spin_unlock_irqrestore(&ieee->lock, flags);
556
557 if (txb) {
558 if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
559 stats->tx_packets++;
560 stats->tx_bytes += txb->payload_size;
561 return 0;
562 }
563 ieee80211_txb_free(txb);
564 }
565 return 0;
566
567 failed:
568 spin_unlock_irqrestore(&ieee->lock, flags);
569 stats->tx_errors++;
570 return 1;
426} 571}
427 572
573EXPORT_SYMBOL(ieee80211_tx_frame);
428EXPORT_SYMBOL(ieee80211_txb_free); 574EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 94882f39b072..ee7a70a13250 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 2
3 Copyright(c) 2004 Intel Corporation. All rights reserved. 3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
4 4
5 Portions of this file are based on the WEP enablement code provided by the 5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3 6 Host AP project hostap-drivers v0.1.3
@@ -32,6 +32,7 @@
32 32
33#include <linux/kmod.h> 33#include <linux/kmod.h>
34#include <linux/module.h> 34#include <linux/module.h>
35#include <linux/jiffies.h>
35 36
36#include <net/ieee80211.h> 37#include <net/ieee80211.h>
37#include <linux/wireless.h> 38#include <linux/wireless.h>
@@ -140,18 +141,38 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
140 start = iwe_stream_add_point(start, stop, &iwe, custom); 141 start = iwe_stream_add_point(start, stop, &iwe, custom);
141 142
142 /* Add quality statistics */ 143 /* Add quality statistics */
143 /* TODO: Fix these values... */
144 iwe.cmd = IWEVQUAL; 144 iwe.cmd = IWEVQUAL;
145 iwe.u.qual.qual = network->stats.signal; 145 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
146 iwe.u.qual.level = network->stats.rssi; 146 IW_QUAL_NOISE_UPDATED;
147 iwe.u.qual.noise = network->stats.noise; 147
148 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK; 148 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
149 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) 149 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
150 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; 150 IW_QUAL_LEVEL_INVALID;
151 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) 151 iwe.u.qual.qual = 0;
152 iwe.u.qual.level = 0;
153 } else {
154 iwe.u.qual.level = network->stats.rssi;
155 iwe.u.qual.qual =
156 (100 *
157 (ieee->perfect_rssi - ieee->worst_rssi) *
158 (ieee->perfect_rssi - ieee->worst_rssi) -
159 (ieee->perfect_rssi - network->stats.rssi) *
160 (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
161 62 * (ieee->perfect_rssi - network->stats.rssi))) /
162 ((ieee->perfect_rssi - ieee->worst_rssi) *
163 (ieee->perfect_rssi - ieee->worst_rssi));
164 if (iwe.u.qual.qual > 100)
165 iwe.u.qual.qual = 100;
166 else if (iwe.u.qual.qual < 1)
167 iwe.u.qual.qual = 0;
168 }
169
170 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
152 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; 171 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
153 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) 172 iwe.u.qual.noise = 0;
154 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID; 173 } else {
174 iwe.u.qual.noise = network->stats.noise;
175 }
155 176
156 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); 177 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
157 178
@@ -162,7 +183,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
162 if (iwe.u.data.length) 183 if (iwe.u.data.length)
163 start = iwe_stream_add_point(start, stop, &iwe, custom); 184 start = iwe_stream_add_point(start, stop, &iwe, custom);
164 185
165 if (ieee->wpa_enabled && network->wpa_ie_len) { 186 if (network->wpa_ie_len) {
166 char buf[MAX_WPA_IE_LEN * 2 + 30]; 187 char buf[MAX_WPA_IE_LEN * 2 + 30];
167 188
168 u8 *p = buf; 189 u8 *p = buf;
@@ -177,7 +198,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
177 start = iwe_stream_add_point(start, stop, &iwe, buf); 198 start = iwe_stream_add_point(start, stop, &iwe, buf);
178 } 199 }
179 200
180 if (ieee->wpa_enabled && network->rsn_ie_len) { 201 if (network->rsn_ie_len) {
181 char buf[MAX_WPA_IE_LEN * 2 + 30]; 202 char buf[MAX_WPA_IE_LEN * 2 + 30];
182 203
183 u8 *p = buf; 204 u8 *p = buf;
@@ -197,8 +218,8 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
197 iwe.cmd = IWEVCUSTOM; 218 iwe.cmd = IWEVCUSTOM;
198 p = custom; 219 p = custom;
199 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), 220 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
200 " Last beacon: %lums ago", 221 " Last beacon: %dms ago",
201 (jiffies - network->last_scanned) / (HZ / 100)); 222 jiffies_to_msecs(jiffies - network->last_scanned));
202 iwe.u.data.length = p - custom; 223 iwe.u.data.length = p - custom;
203 if (iwe.u.data.length) 224 if (iwe.u.data.length)
204 start = iwe_stream_add_point(start, stop, &iwe, custom); 225 start = iwe_stream_add_point(start, stop, &iwe, custom);
@@ -228,13 +249,13 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
228 ev = ipw2100_translate_scan(ieee, ev, stop, network); 249 ev = ipw2100_translate_scan(ieee, ev, stop, network);
229 else 250 else
230 IEEE80211_DEBUG_SCAN("Not showing network '%s (" 251 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
231 MAC_FMT ")' due to age (%lums).\n", 252 MAC_FMT ")' due to age (%dms).\n",
232 escape_essid(network->ssid, 253 escape_essid(network->ssid,
233 network->ssid_len), 254 network->ssid_len),
234 MAC_ARG(network->bssid), 255 MAC_ARG(network->bssid),
235 (jiffies - 256 jiffies_to_msecs(jiffies -
236 network->last_scanned) / (HZ / 257 network->
237 100)); 258 last_scanned));
238 } 259 }
239 260
240 spin_unlock_irqrestore(&ieee->lock, flags); 261 spin_unlock_irqrestore(&ieee->lock, flags);
@@ -258,6 +279,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
258 }; 279 };
259 int i, key, key_provided, len; 280 int i, key, key_provided, len;
260 struct ieee80211_crypt_data **crypt; 281 struct ieee80211_crypt_data **crypt;
282 int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
261 283
262 IEEE80211_DEBUG_WX("SET_ENCODE\n"); 284 IEEE80211_DEBUG_WX("SET_ENCODE\n");
263 285
@@ -298,15 +320,17 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
298 320
299 if (i == WEP_KEYS) { 321 if (i == WEP_KEYS) {
300 sec.enabled = 0; 322 sec.enabled = 0;
323 sec.encrypt = 0;
301 sec.level = SEC_LEVEL_0; 324 sec.level = SEC_LEVEL_0;
302 sec.flags |= SEC_ENABLED | SEC_LEVEL; 325 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
303 } 326 }
304 327
305 goto done; 328 goto done;
306 } 329 }
307 330
308 sec.enabled = 1; 331 sec.enabled = 1;
309 sec.flags |= SEC_ENABLED; 332 sec.encrypt = 1;
333 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
310 334
311 if (*crypt != NULL && (*crypt)->ops != NULL && 335 if (*crypt != NULL && (*crypt)->ops != NULL &&
312 strcmp((*crypt)->ops->name, "WEP") != 0) { 336 strcmp((*crypt)->ops->name, "WEP") != 0) {
@@ -315,7 +339,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
315 ieee80211_crypt_delayed_deinit(ieee, crypt); 339 ieee80211_crypt_delayed_deinit(ieee, crypt);
316 } 340 }
317 341
318 if (*crypt == NULL) { 342 if (*crypt == NULL && host_crypto) {
319 struct ieee80211_crypt_data *new_crypt; 343 struct ieee80211_crypt_data *new_crypt;
320 344
321 /* take WEP into use */ 345 /* take WEP into use */
@@ -355,49 +379,56 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
355 key, escape_essid(sec.keys[key], len), 379 key, escape_essid(sec.keys[key], len),
356 erq->length, len); 380 erq->length, len);
357 sec.key_sizes[key] = len; 381 sec.key_sizes[key] = len;
358 (*crypt)->ops->set_key(sec.keys[key], len, NULL, 382 if (*crypt)
359 (*crypt)->priv); 383 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
384 (*crypt)->priv);
360 sec.flags |= (1 << key); 385 sec.flags |= (1 << key);
361 /* This ensures a key will be activated if no key is 386 /* This ensures a key will be activated if no key is
362 * explicitely set */ 387 * explicitely set */
363 if (key == sec.active_key) 388 if (key == sec.active_key)
364 sec.flags |= SEC_ACTIVE_KEY; 389 sec.flags |= SEC_ACTIVE_KEY;
390
365 } else { 391 } else {
366 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, 392 if (host_crypto) {
367 NULL, (*crypt)->priv); 393 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
368 if (len == 0) { 394 NULL, (*crypt)->priv);
369 /* Set a default key of all 0 */ 395 if (len == 0) {
370 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n", 396 /* Set a default key of all 0 */
371 key); 397 IEEE80211_DEBUG_WX("Setting key %d to all "
372 memset(sec.keys[key], 0, 13); 398 "zero.\n", key);
373 (*crypt)->ops->set_key(sec.keys[key], 13, NULL, 399 memset(sec.keys[key], 0, 13);
374 (*crypt)->priv); 400 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
375 sec.key_sizes[key] = 13; 401 (*crypt)->priv);
376 sec.flags |= (1 << key); 402 sec.key_sizes[key] = 13;
403 sec.flags |= (1 << key);
404 }
377 } 405 }
378
379 /* No key data - just set the default TX key index */ 406 /* No key data - just set the default TX key index */
380 if (key_provided) { 407 if (key_provided) {
381 IEEE80211_DEBUG_WX 408 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
382 ("Setting key %d to default Tx key.\n", key); 409 "key.\n", key);
383 ieee->tx_keyidx = key; 410 ieee->tx_keyidx = key;
384 sec.active_key = key; 411 sec.active_key = key;
385 sec.flags |= SEC_ACTIVE_KEY; 412 sec.flags |= SEC_ACTIVE_KEY;
386 } 413 }
387 } 414 }
388 415 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
389 done: 416 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
390 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); 417 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
391 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; 418 WLAN_AUTH_SHARED_KEY;
392 sec.flags |= SEC_AUTH_MODE; 419 sec.flags |= SEC_AUTH_MODE;
393 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ? 420 IEEE80211_DEBUG_WX("Auth: %s\n",
394 "OPEN" : "SHARED KEY"); 421 sec.auth_mode == WLAN_AUTH_OPEN ?
422 "OPEN" : "SHARED KEY");
423 }
395 424
396 /* For now we just support WEP, so only set that security level... 425 /* For now we just support WEP, so only set that security level...
397 * TODO: When WPA is added this is one place that needs to change */ 426 * TODO: When WPA is added this is one place that needs to change */
398 sec.flags |= SEC_LEVEL; 427 sec.flags |= SEC_LEVEL;
399 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ 428 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
429 sec.encode_alg[key] = SEC_ALG_WEP;
400 430
431 done:
401 if (ieee->set_security) 432 if (ieee->set_security)
402 ieee->set_security(dev, &sec); 433 ieee->set_security(dev, &sec);
403 434
@@ -422,6 +453,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
422 struct iw_point *erq = &(wrqu->encoding); 453 struct iw_point *erq = &(wrqu->encoding);
423 int len, key; 454 int len, key;
424 struct ieee80211_crypt_data *crypt; 455 struct ieee80211_crypt_data *crypt;
456 struct ieee80211_security *sec = &ieee->sec;
425 457
426 IEEE80211_DEBUG_WX("GET_ENCODE\n"); 458 IEEE80211_DEBUG_WX("GET_ENCODE\n");
427 459
@@ -436,23 +468,16 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
436 crypt = ieee->crypt[key]; 468 crypt = ieee->crypt[key];
437 erq->flags = key + 1; 469 erq->flags = key + 1;
438 470
439 if (crypt == NULL || crypt->ops == NULL) { 471 if (!sec->enabled) {
440 erq->length = 0; 472 erq->length = 0;
441 erq->flags |= IW_ENCODE_DISABLED; 473 erq->flags |= IW_ENCODE_DISABLED;
442 return 0; 474 return 0;
443 } 475 }
444 476
445 if (strcmp(crypt->ops->name, "WEP") != 0) { 477 len = sec->key_sizes[key];
446 /* only WEP is supported with wireless extensions, so just 478 memcpy(keybuf, sec->keys[key], len);
447 * report that encryption is used */
448 erq->length = 0;
449 erq->flags |= IW_ENCODE_ENABLED;
450 return 0;
451 }
452 479
453 len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
454 erq->length = (len >= 0 ? len : 0); 480 erq->length = (len >= 0 ? len : 0);
455
456 erq->flags |= IW_ENCODE_ENABLED; 481 erq->flags |= IW_ENCODE_ENABLED;
457 482
458 if (ieee->open_wep) 483 if (ieee->open_wep)
@@ -463,6 +488,240 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
463 return 0; 488 return 0;
464} 489}
465 490
491int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
492 struct iw_request_info *info,
493 union iwreq_data *wrqu, char *extra)
494{
495 struct net_device *dev = ieee->dev;
496 struct iw_point *encoding = &wrqu->encoding;
497 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
498 int i, idx, ret = 0;
499 int group_key = 0;
500 const char *alg, *module;
501 struct ieee80211_crypto_ops *ops;
502 struct ieee80211_crypt_data **crypt;
503
504 struct ieee80211_security sec = {
505 .flags = 0,
506 };
507
508 idx = encoding->flags & IW_ENCODE_INDEX;
509 if (idx) {
510 if (idx < 1 || idx > WEP_KEYS)
511 return -EINVAL;
512 idx--;
513 } else
514 idx = ieee->tx_keyidx;
515
516 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
517 crypt = &ieee->crypt[idx];
518 group_key = 1;
519 } else {
520 if (idx != 0)
521 return -EINVAL;
522 if (ieee->iw_mode == IW_MODE_INFRA)
523 crypt = &ieee->crypt[idx];
524 else
525 return -EINVAL;
526 }
527
528 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
529 if ((encoding->flags & IW_ENCODE_DISABLED) ||
530 ext->alg == IW_ENCODE_ALG_NONE) {
531 if (*crypt)
532 ieee80211_crypt_delayed_deinit(ieee, crypt);
533
534 for (i = 0; i < WEP_KEYS; i++)
535 if (ieee->crypt[i] != NULL)
536 break;
537
538 if (i == WEP_KEYS) {
539 sec.enabled = 0;
540 sec.encrypt = 0;
541 sec.level = SEC_LEVEL_0;
542 sec.flags |= SEC_LEVEL;
543 }
544 goto done;
545 }
546
547 sec.enabled = 1;
548 sec.encrypt = 1;
549
550 if (group_key ? !ieee->host_mc_decrypt :
551 !(ieee->host_encrypt || ieee->host_decrypt ||
552 ieee->host_encrypt_msdu))
553 goto skip_host_crypt;
554
555 switch (ext->alg) {
556 case IW_ENCODE_ALG_WEP:
557 alg = "WEP";
558 module = "ieee80211_crypt_wep";
559 break;
560 case IW_ENCODE_ALG_TKIP:
561 alg = "TKIP";
562 module = "ieee80211_crypt_tkip";
563 break;
564 case IW_ENCODE_ALG_CCMP:
565 alg = "CCMP";
566 module = "ieee80211_crypt_ccmp";
567 break;
568 default:
569 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
570 dev->name, ext->alg);
571 ret = -EINVAL;
572 goto done;
573 }
574
575 ops = ieee80211_get_crypto_ops(alg);
576 if (ops == NULL) {
577 request_module(module);
578 ops = ieee80211_get_crypto_ops(alg);
579 }
580 if (ops == NULL) {
581 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
582 dev->name, ext->alg);
583 ret = -EINVAL;
584 goto done;
585 }
586
587 if (*crypt == NULL || (*crypt)->ops != ops) {
588 struct ieee80211_crypt_data *new_crypt;
589
590 ieee80211_crypt_delayed_deinit(ieee, crypt);
591
592 new_crypt = (struct ieee80211_crypt_data *)
593 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
594 if (new_crypt == NULL) {
595 ret = -ENOMEM;
596 goto done;
597 }
598 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
599 new_crypt->ops = ops;
600 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
601 new_crypt->priv = new_crypt->ops->init(idx);
602 if (new_crypt->priv == NULL) {
603 kfree(new_crypt);
604 ret = -EINVAL;
605 goto done;
606 }
607 *crypt = new_crypt;
608 }
609
610 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
611 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
612 (*crypt)->priv) < 0) {
613 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
614 ret = -EINVAL;
615 goto done;
616 }
617
618 skip_host_crypt:
619 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
620 ieee->tx_keyidx = idx;
621 sec.active_key = idx;
622 sec.flags |= SEC_ACTIVE_KEY;
623 }
624
625 if (ext->alg != IW_ENCODE_ALG_NONE) {
626 memcpy(sec.keys[idx], ext->key, ext->key_len);
627 sec.key_sizes[idx] = ext->key_len;
628 sec.flags |= (1 << idx);
629 if (ext->alg == IW_ENCODE_ALG_WEP) {
630 sec.encode_alg[idx] = SEC_ALG_WEP;
631 sec.flags |= SEC_LEVEL;
632 sec.level = SEC_LEVEL_1;
633 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
634 sec.encode_alg[idx] = SEC_ALG_TKIP;
635 sec.flags |= SEC_LEVEL;
636 sec.level = SEC_LEVEL_2;
637 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
638 sec.encode_alg[idx] = SEC_ALG_CCMP;
639 sec.flags |= SEC_LEVEL;
640 sec.level = SEC_LEVEL_3;
641 }
642 /* Don't set sec level for group keys. */
643 if (group_key)
644 sec.flags &= ~SEC_LEVEL;
645 }
646 done:
647 if (ieee->set_security)
648 ieee->set_security(ieee->dev, &sec);
649
650 /*
651 * Do not reset port if card is in Managed mode since resetting will
652 * generate new IEEE 802.11 authentication which may end up in looping
653 * with IEEE 802.1X. If your hardware requires a reset after WEP
654 * configuration (for example... Prism2), implement the reset_port in
655 * the callbacks structures used to initialize the 802.11 stack.
656 */
657 if (ieee->reset_on_keychange &&
658 ieee->iw_mode != IW_MODE_INFRA &&
659 ieee->reset_port && ieee->reset_port(dev)) {
660 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
661 return -EINVAL;
662 }
663
664 return ret;
665}
666
667int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
668 struct iw_request_info *info,
669 union iwreq_data *wrqu, char *extra)
670{
671 struct iw_point *encoding = &wrqu->encoding;
672 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
673 struct ieee80211_security *sec = &ieee->sec;
674 int idx, max_key_len;
675
676 max_key_len = encoding->length - sizeof(*ext);
677 if (max_key_len < 0)
678 return -EINVAL;
679
680 idx = encoding->flags & IW_ENCODE_INDEX;
681 if (idx) {
682 if (idx < 1 || idx > WEP_KEYS)
683 return -EINVAL;
684 idx--;
685 } else
686 idx = ieee->tx_keyidx;
687
688 if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
689 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
690 return -EINVAL;
691
692 encoding->flags = idx + 1;
693 memset(ext, 0, sizeof(*ext));
694
695 if (!sec->enabled) {
696 ext->alg = IW_ENCODE_ALG_NONE;
697 ext->key_len = 0;
698 encoding->flags |= IW_ENCODE_DISABLED;
699 } else {
700 if (sec->encode_alg[idx] == SEC_ALG_WEP)
701 ext->alg = IW_ENCODE_ALG_WEP;
702 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
703 ext->alg = IW_ENCODE_ALG_TKIP;
704 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
705 ext->alg = IW_ENCODE_ALG_CCMP;
706 else
707 return -EINVAL;
708
709 ext->key_len = sec->key_sizes[idx];
710 memcpy(ext->key, sec->keys[idx], ext->key_len);
711 encoding->flags |= IW_ENCODE_ENABLED;
712 if (ext->key_len &&
713 (ext->alg == IW_ENCODE_ALG_TKIP ||
714 ext->alg == IW_ENCODE_ALG_CCMP))
715 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
716
717 }
718
719 return 0;
720}
721
722EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
723EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
724
466EXPORT_SYMBOL(ieee80211_wx_get_scan); 725EXPORT_SYMBOL(ieee80211_wx_get_scan);
467EXPORT_SYMBOL(ieee80211_wx_set_encode); 726EXPORT_SYMBOL(ieee80211_wx_set_encode);
468EXPORT_SYMBOL(ieee80211_wx_get_encode); 727EXPORT_SYMBOL(ieee80211_wx_get_encode);