aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/Kconfig73
-rw-r--r--net/ieee80211/Makefile12
-rw-r--r--net/ieee80211/ieee80211_crypt.c206
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c493
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c787
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c295
-rw-r--r--net/ieee80211/ieee80211_geo.c195
-rw-r--r--net/ieee80211/ieee80211_module.c338
-rw-r--r--net/ieee80211/ieee80211_rx.c1831
-rw-r--r--net/ieee80211/ieee80211_tx.c545
-rw-r--r--net/ieee80211/ieee80211_wx.c760
11 files changed, 0 insertions, 5535 deletions
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
deleted file mode 100644
index 94ed7d3cd9da..000000000000
--- a/net/ieee80211/Kconfig
+++ /dev/null
@@ -1,73 +0,0 @@
1config IEEE80211
2 tristate "Generic IEEE 802.11 Networking Stack (DEPRECATED)"
3 ---help---
4 This option enables the hardware independent IEEE 802.11
5 networking stack. This component is deprecated in favor of the
6 mac80211 component.
7
8config IEEE80211_DEBUG
9 bool "Enable full debugging output"
10 depends on IEEE80211
11 ---help---
12 This option will enable debug tracing output for the
13 ieee80211 network stack.
14
15 This will result in the kernel module being ~70k larger. You
16 can control which debug output is sent to the kernel log by
17 setting the value in
18
19 /proc/net/ieee80211/debug_level
20
21 For example:
22
23 % echo 0x00000FFO > /proc/net/ieee80211/debug_level
24
25 For a list of values you can assign to debug_level, you
26 can look at the bit mask values in <net/ieee80211.h>
27
28 If you are not trying to debug or develop the ieee80211
29 subsystem, you most likely want to say N here.
30
31config IEEE80211_CRYPT_WEP
32 tristate "IEEE 802.11 WEP encryption (802.1x)"
33 depends on IEEE80211
34 select CRYPTO
35 select CRYPTO_ARC4
36 select CRYPTO_ECB
37 select CRC32
38 ---help---
39 Include software based cipher suites in support of IEEE
40 802.11's WEP. This is needed for WEP as well as 802.1x.
41
42 This can be compiled as a module and it will be called
43 "ieee80211_crypt_wep".
44
45config IEEE80211_CRYPT_CCMP
46 tristate "IEEE 802.11i CCMP support"
47 depends on IEEE80211
48 select CRYPTO
49 select CRYPTO_AES
50 ---help---
51 Include software based cipher suites in support of IEEE 802.11i
52 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled
53 networks.
54
55 This can be compiled as a module and it will be called
56 "ieee80211_crypt_ccmp".
57
58config IEEE80211_CRYPT_TKIP
59 tristate "IEEE 802.11i TKIP encryption"
60 depends on IEEE80211
61 select WIRELESS_EXT
62 select CRYPTO
63 select CRYPTO_MICHAEL_MIC
64 select CRYPTO_ECB
65 select CRC32
66 ---help---
67 Include software based cipher suites in support of IEEE 802.11i
68 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled
69 networks.
70
71 This can be compiled as a module and it will be called
72 "ieee80211_crypt_tkip".
73
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
deleted file mode 100644
index f988417121da..000000000000
--- a/net/ieee80211/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
1obj-$(CONFIG_IEEE80211) += ieee80211.o
2obj-$(CONFIG_IEEE80211) += ieee80211_crypt.o
3obj-$(CONFIG_IEEE80211_CRYPT_WEP) += ieee80211_crypt_wep.o
4obj-$(CONFIG_IEEE80211_CRYPT_CCMP) += ieee80211_crypt_ccmp.o
5obj-$(CONFIG_IEEE80211_CRYPT_TKIP) += ieee80211_crypt_tkip.o
6ieee80211-objs := \
7 ieee80211_module.o \
8 ieee80211_tx.o \
9 ieee80211_rx.o \
10 ieee80211_wx.o \
11 ieee80211_geo.o
12
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
deleted file mode 100644
index df5592c9339f..000000000000
--- a/net/ieee80211/ieee80211_crypt.c
+++ /dev/null
@@ -1,206 +0,0 @@
1/*
2 * Host AP crypto routines
3 *
4 * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
5 * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. See README and COPYING for
10 * more details.
11 *
12 */
13
14#include <linux/errno.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/string.h>
19#include <net/ieee80211.h>
20
21MODULE_AUTHOR("Jouni Malinen");
22MODULE_DESCRIPTION("HostAP crypto");
23MODULE_LICENSE("GPL");
24
25struct ieee80211_crypto_alg {
26 struct list_head list;
27 struct ieee80211_crypto_ops *ops;
28};
29
30static LIST_HEAD(ieee80211_crypto_algs);
31static DEFINE_SPINLOCK(ieee80211_crypto_lock);
32
33void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
34{
35 struct ieee80211_crypt_data *entry, *next;
36 unsigned long flags;
37
38 spin_lock_irqsave(&ieee->lock, flags);
39 list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) {
40 if (atomic_read(&entry->refcnt) != 0 && !force)
41 continue;
42
43 list_del(&entry->list);
44
45 if (entry->ops) {
46 entry->ops->deinit(entry->priv);
47 module_put(entry->ops->owner);
48 }
49 kfree(entry);
50 }
51 spin_unlock_irqrestore(&ieee->lock, flags);
52}
53
54/* After this, crypt_deinit_list won't accept new members */
55void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
56{
57 unsigned long flags;
58
59 spin_lock_irqsave(&ieee->lock, flags);
60 ieee->crypt_quiesced = 1;
61 spin_unlock_irqrestore(&ieee->lock, flags);
62}
63
64void ieee80211_crypt_deinit_handler(unsigned long data)
65{
66 struct ieee80211_device *ieee = (struct ieee80211_device *)data;
67 unsigned long flags;
68
69 ieee80211_crypt_deinit_entries(ieee, 0);
70
71 spin_lock_irqsave(&ieee->lock, flags);
72 if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
73 printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
74 "deletion list\n", ieee->dev->name);
75 ieee->crypt_deinit_timer.expires = jiffies + HZ;
76 add_timer(&ieee->crypt_deinit_timer);
77 }
78 spin_unlock_irqrestore(&ieee->lock, flags);
79}
80
81void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
82 struct ieee80211_crypt_data **crypt)
83{
84 struct ieee80211_crypt_data *tmp;
85 unsigned long flags;
86
87 if (*crypt == NULL)
88 return;
89
90 tmp = *crypt;
91 *crypt = NULL;
92
93 /* must not run ops->deinit() while there may be pending encrypt or
94 * decrypt operations. Use a list of delayed deinits to avoid needing
95 * locking. */
96
97 spin_lock_irqsave(&ieee->lock, flags);
98 if (!ieee->crypt_quiesced) {
99 list_add(&tmp->list, &ieee->crypt_deinit_list);
100 if (!timer_pending(&ieee->crypt_deinit_timer)) {
101 ieee->crypt_deinit_timer.expires = jiffies + HZ;
102 add_timer(&ieee->crypt_deinit_timer);
103 }
104 }
105 spin_unlock_irqrestore(&ieee->lock, flags);
106}
107
108int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
109{
110 unsigned long flags;
111 struct ieee80211_crypto_alg *alg;
112
113 alg = kzalloc(sizeof(*alg), GFP_KERNEL);
114 if (alg == NULL)
115 return -ENOMEM;
116
117 alg->ops = ops;
118
119 spin_lock_irqsave(&ieee80211_crypto_lock, flags);
120 list_add(&alg->list, &ieee80211_crypto_algs);
121 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
122
123 printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
124 ops->name);
125
126 return 0;
127}
128
129int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
130{
131 struct ieee80211_crypto_alg *alg;
132 unsigned long flags;
133
134 spin_lock_irqsave(&ieee80211_crypto_lock, flags);
135 list_for_each_entry(alg, &ieee80211_crypto_algs, list) {
136 if (alg->ops == ops)
137 goto found;
138 }
139 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
140 return -EINVAL;
141
142 found:
143 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
144 "'%s'\n", ops->name);
145 list_del(&alg->list);
146 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
147 kfree(alg);
148 return 0;
149}
150
151struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
152{
153 struct ieee80211_crypto_alg *alg;
154 unsigned long flags;
155
156 spin_lock_irqsave(&ieee80211_crypto_lock, flags);
157 list_for_each_entry(alg, &ieee80211_crypto_algs, list) {
158 if (strcmp(alg->ops->name, name) == 0)
159 goto found;
160 }
161 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
162 return NULL;
163
164 found:
165 spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
166 return alg->ops;
167}
168
169static void *ieee80211_crypt_null_init(int keyidx)
170{
171 return (void *)1;
172}
173
174static void ieee80211_crypt_null_deinit(void *priv)
175{
176}
177
178static struct ieee80211_crypto_ops ieee80211_crypt_null = {
179 .name = "NULL",
180 .init = ieee80211_crypt_null_init,
181 .deinit = ieee80211_crypt_null_deinit,
182 .owner = THIS_MODULE,
183};
184
185static int __init ieee80211_crypto_init(void)
186{
187 return ieee80211_register_crypto_ops(&ieee80211_crypt_null);
188}
189
190static void __exit ieee80211_crypto_deinit(void)
191{
192 ieee80211_unregister_crypto_ops(&ieee80211_crypt_null);
193 BUG_ON(!list_empty(&ieee80211_crypto_algs));
194}
195
196EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
197EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
198EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
199EXPORT_SYMBOL(ieee80211_crypt_quiescing);
200
201EXPORT_SYMBOL(ieee80211_register_crypto_ops);
202EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
203EXPORT_SYMBOL(ieee80211_get_crypto_ops);
204
205module_init(ieee80211_crypto_init);
206module_exit(ieee80211_crypto_deinit);
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
deleted file mode 100644
index 208bf35b5546..000000000000
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ /dev/null
@@ -1,493 +0,0 @@
1/*
2 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/kernel.h>
13#include <linux/err.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/random.h>
18#include <linux/skbuff.h>
19#include <linux/netdevice.h>
20#include <linux/if_ether.h>
21#include <linux/if_arp.h>
22#include <asm/string.h>
23#include <linux/wireless.h>
24
25#include <net/ieee80211.h>
26
27#include <linux/crypto.h>
28
29MODULE_AUTHOR("Jouni Malinen");
30MODULE_DESCRIPTION("Host AP crypt: CCMP");
31MODULE_LICENSE("GPL");
32
33#define AES_BLOCK_LEN 16
34#define CCMP_HDR_LEN 8
35#define CCMP_MIC_LEN 8
36#define CCMP_TK_LEN 16
37#define CCMP_PN_LEN 6
38
39struct ieee80211_ccmp_data {
40 u8 key[CCMP_TK_LEN];
41 int key_set;
42
43 u8 tx_pn[CCMP_PN_LEN];
44 u8 rx_pn[CCMP_PN_LEN];
45
46 u32 dot11RSNAStatsCCMPFormatErrors;
47 u32 dot11RSNAStatsCCMPReplays;
48 u32 dot11RSNAStatsCCMPDecryptErrors;
49
50 int key_idx;
51
52 struct crypto_cipher *tfm;
53
54 /* scratch buffers for virt_to_page() (crypto API) */
55 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
56 tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
57 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
58};
59
60static inline void ieee80211_ccmp_aes_encrypt(struct crypto_cipher *tfm,
61 const u8 pt[16], u8 ct[16])
62{
63 crypto_cipher_encrypt_one(tfm, ct, pt);
64}
65
66static void *ieee80211_ccmp_init(int key_idx)
67{
68 struct ieee80211_ccmp_data *priv;
69
70 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
71 if (priv == NULL)
72 goto fail;
73 priv->key_idx = key_idx;
74
75 priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
76 if (IS_ERR(priv->tfm)) {
77 printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
78 "crypto API aes\n");
79 priv->tfm = NULL;
80 goto fail;
81 }
82
83 return priv;
84
85 fail:
86 if (priv) {
87 if (priv->tfm)
88 crypto_free_cipher(priv->tfm);
89 kfree(priv);
90 }
91
92 return NULL;
93}
94
95static void ieee80211_ccmp_deinit(void *priv)
96{
97 struct ieee80211_ccmp_data *_priv = priv;
98 if (_priv && _priv->tfm)
99 crypto_free_cipher(_priv->tfm);
100 kfree(priv);
101}
102
103static inline void xor_block(u8 * b, u8 * a, size_t len)
104{
105 int i;
106 for (i = 0; i < len; i++)
107 b[i] ^= a[i];
108}
109
110static void ccmp_init_blocks(struct crypto_cipher *tfm,
111 struct ieee80211_hdr_4addr *hdr,
112 u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
113{
114 u8 *pos, qc = 0;
115 size_t aad_len;
116 u16 fc;
117 int a4_included, qc_included;
118 u8 aad[2 * AES_BLOCK_LEN];
119
120 fc = le16_to_cpu(hdr->frame_ctl);
121 a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
122 (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
123 qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
124 (WLAN_FC_GET_STYPE(fc) & IEEE80211_STYPE_QOS_DATA));
125 aad_len = 22;
126 if (a4_included)
127 aad_len += 6;
128 if (qc_included) {
129 pos = (u8 *) & hdr->addr4;
130 if (a4_included)
131 pos += 6;
132 qc = *pos & 0x0f;
133 aad_len += 2;
134 }
135
136 /* CCM Initial Block:
137 * Flag (Include authentication header, M=3 (8-octet MIC),
138 * L=1 (2-octet Dlen))
139 * Nonce: 0x00 | A2 | PN
140 * Dlen */
141 b0[0] = 0x59;
142 b0[1] = qc;
143 memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
144 memcpy(b0 + 8, pn, CCMP_PN_LEN);
145 b0[14] = (dlen >> 8) & 0xff;
146 b0[15] = dlen & 0xff;
147
148 /* AAD:
149 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
150 * A1 | A2 | A3
151 * SC with bits 4..15 (seq#) masked to zero
152 * A4 (if present)
153 * QC (if present)
154 */
155 pos = (u8 *) hdr;
156 aad[0] = 0; /* aad_len >> 8 */
157 aad[1] = aad_len & 0xff;
158 aad[2] = pos[0] & 0x8f;
159 aad[3] = pos[1] & 0xc7;
160 memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
161 pos = (u8 *) & hdr->seq_ctl;
162 aad[22] = pos[0] & 0x0f;
163 aad[23] = 0; /* all bits masked */
164 memset(aad + 24, 0, 8);
165 if (a4_included)
166 memcpy(aad + 24, hdr->addr4, ETH_ALEN);
167 if (qc_included) {
168 aad[a4_included ? 30 : 24] = qc;
169 /* rest of QC masked */
170 }
171
172 /* Start with the first block and AAD */
173 ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
174 xor_block(auth, aad, AES_BLOCK_LEN);
175 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
176 xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
177 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
178 b0[0] &= 0x07;
179 b0[14] = b0[15] = 0;
180 ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
181}
182
183static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
184 u8 *aeskey, int keylen, void *priv)
185{
186 struct ieee80211_ccmp_data *key = priv;
187 int i;
188 u8 *pos;
189
190 if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
191 return -1;
192
193 if (aeskey != NULL && keylen >= CCMP_TK_LEN)
194 memcpy(aeskey, key->key, CCMP_TK_LEN);
195
196 pos = skb_push(skb, CCMP_HDR_LEN);
197 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
198 pos += hdr_len;
199
200 i = CCMP_PN_LEN - 1;
201 while (i >= 0) {
202 key->tx_pn[i]++;
203 if (key->tx_pn[i] != 0)
204 break;
205 i--;
206 }
207
208 *pos++ = key->tx_pn[5];
209 *pos++ = key->tx_pn[4];
210 *pos++ = 0;
211 *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
212 *pos++ = key->tx_pn[3];
213 *pos++ = key->tx_pn[2];
214 *pos++ = key->tx_pn[1];
215 *pos++ = key->tx_pn[0];
216
217 return CCMP_HDR_LEN;
218}
219
220static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
221{
222 struct ieee80211_ccmp_data *key = priv;
223 int data_len, i, blocks, last, len;
224 u8 *pos, *mic;
225 struct ieee80211_hdr_4addr *hdr;
226 u8 *b0 = key->tx_b0;
227 u8 *b = key->tx_b;
228 u8 *e = key->tx_e;
229 u8 *s0 = key->tx_s0;
230
231 if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
232 return -1;
233
234 data_len = skb->len - hdr_len;
235 len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
236 if (len < 0)
237 return -1;
238
239 pos = skb->data + hdr_len + CCMP_HDR_LEN;
240 mic = skb_put(skb, CCMP_MIC_LEN);
241 hdr = (struct ieee80211_hdr_4addr *)skb->data;
242 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
243
244 blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
245 last = data_len % AES_BLOCK_LEN;
246
247 for (i = 1; i <= blocks; i++) {
248 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
249 /* Authentication */
250 xor_block(b, pos, len);
251 ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
252 /* Encryption, with counter */
253 b0[14] = (i >> 8) & 0xff;
254 b0[15] = i & 0xff;
255 ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
256 xor_block(pos, e, len);
257 pos += len;
258 }
259
260 for (i = 0; i < CCMP_MIC_LEN; i++)
261 mic[i] = b[i] ^ s0[i];
262
263 return 0;
264}
265
266/*
267 * deal with seq counter wrapping correctly.
268 * refer to timer_after() for jiffies wrapping handling
269 */
270static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o)
271{
272 u32 iv32_n, iv16_n;
273 u32 iv32_o, iv16_o;
274
275 iv32_n = (pn_n[0] << 24) | (pn_n[1] << 16) | (pn_n[2] << 8) | pn_n[3];
276 iv16_n = (pn_n[4] << 8) | pn_n[5];
277
278 iv32_o = (pn_o[0] << 24) | (pn_o[1] << 16) | (pn_o[2] << 8) | pn_o[3];
279 iv16_o = (pn_o[4] << 8) | pn_o[5];
280
281 if ((s32)iv32_n - (s32)iv32_o < 0 ||
282 (iv32_n == iv32_o && iv16_n <= iv16_o))
283 return 1;
284 return 0;
285}
286
287static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
288{
289 struct ieee80211_ccmp_data *key = priv;
290 u8 keyidx, *pos;
291 struct ieee80211_hdr_4addr *hdr;
292 u8 *b0 = key->rx_b0;
293 u8 *b = key->rx_b;
294 u8 *a = key->rx_a;
295 u8 pn[6];
296 int i, blocks, last, len;
297 size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
298 u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
299 DECLARE_MAC_BUF(mac);
300
301 if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
302 key->dot11RSNAStatsCCMPFormatErrors++;
303 return -1;
304 }
305
306 hdr = (struct ieee80211_hdr_4addr *)skb->data;
307 pos = skb->data + hdr_len;
308 keyidx = pos[3];
309 if (!(keyidx & (1 << 5))) {
310 if (net_ratelimit()) {
311 printk(KERN_DEBUG "CCMP: received packet without ExtIV"
312 " flag from %s\n", print_mac(mac, hdr->addr2));
313 }
314 key->dot11RSNAStatsCCMPFormatErrors++;
315 return -2;
316 }
317 keyidx >>= 6;
318 if (key->key_idx != keyidx) {
319 printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
320 "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
321 return -6;
322 }
323 if (!key->key_set) {
324 if (net_ratelimit()) {
325 printk(KERN_DEBUG "CCMP: received packet from %s"
326 " with keyid=%d that does not have a configured"
327 " key\n", print_mac(mac, hdr->addr2), keyidx);
328 }
329 return -3;
330 }
331
332 pn[0] = pos[7];
333 pn[1] = pos[6];
334 pn[2] = pos[5];
335 pn[3] = pos[4];
336 pn[4] = pos[1];
337 pn[5] = pos[0];
338 pos += 8;
339
340 if (ccmp_replay_check(pn, key->rx_pn)) {
341 if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
342 IEEE80211_DEBUG_DROP("CCMP: replay detected: STA=%s "
343 "previous PN %02x%02x%02x%02x%02x%02x "
344 "received PN %02x%02x%02x%02x%02x%02x\n",
345 print_mac(mac, hdr->addr2),
346 key->rx_pn[0], key->rx_pn[1], key->rx_pn[2],
347 key->rx_pn[3], key->rx_pn[4], key->rx_pn[5],
348 pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]);
349 }
350 key->dot11RSNAStatsCCMPReplays++;
351 return -4;
352 }
353
354 ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
355 xor_block(mic, b, CCMP_MIC_LEN);
356
357 blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
358 last = data_len % AES_BLOCK_LEN;
359
360 for (i = 1; i <= blocks; i++) {
361 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
362 /* Decrypt, with counter */
363 b0[14] = (i >> 8) & 0xff;
364 b0[15] = i & 0xff;
365 ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
366 xor_block(pos, b, len);
367 /* Authentication */
368 xor_block(a, pos, len);
369 ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
370 pos += len;
371 }
372
373 if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
374 if (net_ratelimit()) {
375 printk(KERN_DEBUG "CCMP: decrypt failed: STA="
376 "%s\n", print_mac(mac, hdr->addr2));
377 }
378 key->dot11RSNAStatsCCMPDecryptErrors++;
379 return -5;
380 }
381
382 memcpy(key->rx_pn, pn, CCMP_PN_LEN);
383
384 /* Remove hdr and MIC */
385 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
386 skb_pull(skb, CCMP_HDR_LEN);
387 skb_trim(skb, skb->len - CCMP_MIC_LEN);
388
389 return keyidx;
390}
391
392static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
393{
394 struct ieee80211_ccmp_data *data = priv;
395 int keyidx;
396 struct crypto_cipher *tfm = data->tfm;
397
398 keyidx = data->key_idx;
399 memset(data, 0, sizeof(*data));
400 data->key_idx = keyidx;
401 data->tfm = tfm;
402 if (len == CCMP_TK_LEN) {
403 memcpy(data->key, key, CCMP_TK_LEN);
404 data->key_set = 1;
405 if (seq) {
406 data->rx_pn[0] = seq[5];
407 data->rx_pn[1] = seq[4];
408 data->rx_pn[2] = seq[3];
409 data->rx_pn[3] = seq[2];
410 data->rx_pn[4] = seq[1];
411 data->rx_pn[5] = seq[0];
412 }
413 crypto_cipher_setkey(data->tfm, data->key, CCMP_TK_LEN);
414 } else if (len == 0)
415 data->key_set = 0;
416 else
417 return -1;
418
419 return 0;
420}
421
422static int ieee80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
423{
424 struct ieee80211_ccmp_data *data = priv;
425
426 if (len < CCMP_TK_LEN)
427 return -1;
428
429 if (!data->key_set)
430 return 0;
431 memcpy(key, data->key, CCMP_TK_LEN);
432
433 if (seq) {
434 seq[0] = data->tx_pn[5];
435 seq[1] = data->tx_pn[4];
436 seq[2] = data->tx_pn[3];
437 seq[3] = data->tx_pn[2];
438 seq[4] = data->tx_pn[1];
439 seq[5] = data->tx_pn[0];
440 }
441
442 return CCMP_TK_LEN;
443}
444
445static char *ieee80211_ccmp_print_stats(char *p, void *priv)
446{
447 struct ieee80211_ccmp_data *ccmp = priv;
448
449 p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
450 "tx_pn=%02x%02x%02x%02x%02x%02x "
451 "rx_pn=%02x%02x%02x%02x%02x%02x "
452 "format_errors=%d replays=%d decrypt_errors=%d\n",
453 ccmp->key_idx, ccmp->key_set,
454 ccmp->tx_pn[0], ccmp->tx_pn[1], ccmp->tx_pn[2],
455 ccmp->tx_pn[3], ccmp->tx_pn[4], ccmp->tx_pn[5],
456 ccmp->rx_pn[0], ccmp->rx_pn[1], ccmp->rx_pn[2],
457 ccmp->rx_pn[3], ccmp->rx_pn[4], ccmp->rx_pn[5],
458 ccmp->dot11RSNAStatsCCMPFormatErrors,
459 ccmp->dot11RSNAStatsCCMPReplays,
460 ccmp->dot11RSNAStatsCCMPDecryptErrors);
461
462 return p;
463}
464
465static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
466 .name = "CCMP",
467 .init = ieee80211_ccmp_init,
468 .deinit = ieee80211_ccmp_deinit,
469 .build_iv = ieee80211_ccmp_hdr,
470 .encrypt_mpdu = ieee80211_ccmp_encrypt,
471 .decrypt_mpdu = ieee80211_ccmp_decrypt,
472 .encrypt_msdu = NULL,
473 .decrypt_msdu = NULL,
474 .set_key = ieee80211_ccmp_set_key,
475 .get_key = ieee80211_ccmp_get_key,
476 .print_stats = ieee80211_ccmp_print_stats,
477 .extra_mpdu_prefix_len = CCMP_HDR_LEN,
478 .extra_mpdu_postfix_len = CCMP_MIC_LEN,
479 .owner = THIS_MODULE,
480};
481
482static int __init ieee80211_crypto_ccmp_init(void)
483{
484 return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
485}
486
487static void __exit ieee80211_crypto_ccmp_exit(void)
488{
489 ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
490}
491
492module_init(ieee80211_crypto_ccmp_init);
493module_exit(ieee80211_crypto_ccmp_exit);
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
deleted file mode 100644
index bba0152e2d71..000000000000
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ /dev/null
@@ -1,787 +0,0 @@
1/*
2 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/err.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/random.h>
17#include <linux/scatterlist.h>
18#include <linux/skbuff.h>
19#include <linux/netdevice.h>
20#include <linux/mm.h>
21#include <linux/if_ether.h>
22#include <linux/if_arp.h>
23#include <asm/string.h>
24
25#include <net/ieee80211.h>
26
27#include <linux/crypto.h>
28#include <linux/crc32.h>
29
30MODULE_AUTHOR("Jouni Malinen");
31MODULE_DESCRIPTION("Host AP crypt: TKIP");
32MODULE_LICENSE("GPL");
33
34struct ieee80211_tkip_data {
35#define TKIP_KEY_LEN 32
36 u8 key[TKIP_KEY_LEN];
37 int key_set;
38
39 u32 tx_iv32;
40 u16 tx_iv16;
41 u16 tx_ttak[5];
42 int tx_phase1_done;
43
44 u32 rx_iv32;
45 u16 rx_iv16;
46 u16 rx_ttak[5];
47 int rx_phase1_done;
48 u32 rx_iv32_new;
49 u16 rx_iv16_new;
50
51 u32 dot11RSNAStatsTKIPReplays;
52 u32 dot11RSNAStatsTKIPICVErrors;
53 u32 dot11RSNAStatsTKIPLocalMICFailures;
54
55 int key_idx;
56
57 struct crypto_blkcipher *rx_tfm_arc4;
58 struct crypto_hash *rx_tfm_michael;
59 struct crypto_blkcipher *tx_tfm_arc4;
60 struct crypto_hash *tx_tfm_michael;
61
62 /* scratch buffers for virt_to_page() (crypto API) */
63 u8 rx_hdr[16], tx_hdr[16];
64
65 unsigned long flags;
66};
67
68static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
69{
70 struct ieee80211_tkip_data *_priv = priv;
71 unsigned long old_flags = _priv->flags;
72 _priv->flags = flags;
73 return old_flags;
74}
75
76static unsigned long ieee80211_tkip_get_flags(void *priv)
77{
78 struct ieee80211_tkip_data *_priv = priv;
79 return _priv->flags;
80}
81
82static void *ieee80211_tkip_init(int key_idx)
83{
84 struct ieee80211_tkip_data *priv;
85
86 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
87 if (priv == NULL)
88 goto fail;
89
90 priv->key_idx = key_idx;
91
92 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
93 CRYPTO_ALG_ASYNC);
94 if (IS_ERR(priv->tx_tfm_arc4)) {
95 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
96 "crypto API arc4\n");
97 priv->tx_tfm_arc4 = NULL;
98 goto fail;
99 }
100
101 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
102 CRYPTO_ALG_ASYNC);
103 if (IS_ERR(priv->tx_tfm_michael)) {
104 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
105 "crypto API michael_mic\n");
106 priv->tx_tfm_michael = NULL;
107 goto fail;
108 }
109
110 priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
111 CRYPTO_ALG_ASYNC);
112 if (IS_ERR(priv->rx_tfm_arc4)) {
113 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
114 "crypto API arc4\n");
115 priv->rx_tfm_arc4 = NULL;
116 goto fail;
117 }
118
119 priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
120 CRYPTO_ALG_ASYNC);
121 if (IS_ERR(priv->rx_tfm_michael)) {
122 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
123 "crypto API michael_mic\n");
124 priv->rx_tfm_michael = NULL;
125 goto fail;
126 }
127
128 return priv;
129
130 fail:
131 if (priv) {
132 if (priv->tx_tfm_michael)
133 crypto_free_hash(priv->tx_tfm_michael);
134 if (priv->tx_tfm_arc4)
135 crypto_free_blkcipher(priv->tx_tfm_arc4);
136 if (priv->rx_tfm_michael)
137 crypto_free_hash(priv->rx_tfm_michael);
138 if (priv->rx_tfm_arc4)
139 crypto_free_blkcipher(priv->rx_tfm_arc4);
140 kfree(priv);
141 }
142
143 return NULL;
144}
145
146static void ieee80211_tkip_deinit(void *priv)
147{
148 struct ieee80211_tkip_data *_priv = priv;
149 if (_priv) {
150 if (_priv->tx_tfm_michael)
151 crypto_free_hash(_priv->tx_tfm_michael);
152 if (_priv->tx_tfm_arc4)
153 crypto_free_blkcipher(_priv->tx_tfm_arc4);
154 if (_priv->rx_tfm_michael)
155 crypto_free_hash(_priv->rx_tfm_michael);
156 if (_priv->rx_tfm_arc4)
157 crypto_free_blkcipher(_priv->rx_tfm_arc4);
158 }
159 kfree(priv);
160}
161
162static inline u16 RotR1(u16 val)
163{
164 return (val >> 1) | (val << 15);
165}
166
167static inline u8 Lo8(u16 val)
168{
169 return val & 0xff;
170}
171
172static inline u8 Hi8(u16 val)
173{
174 return val >> 8;
175}
176
177static inline u16 Lo16(u32 val)
178{
179 return val & 0xffff;
180}
181
182static inline u16 Hi16(u32 val)
183{
184 return val >> 16;
185}
186
187static inline u16 Mk16(u8 hi, u8 lo)
188{
189 return lo | (((u16) hi) << 8);
190}
191
192static inline u16 Mk16_le(__le16 * v)
193{
194 return le16_to_cpu(*v);
195}
196
197static const u16 Sbox[256] = {
198 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
199 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
200 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
201 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
202 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
203 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
204 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
205 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
206 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
207 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
208 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
209 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
210 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
211 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
212 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
213 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
214 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
215 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
216 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
217 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
218 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
219 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
220 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
221 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
222 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
223 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
224 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
225 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
226 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
227 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
228 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
229 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
230};
231
232static inline u16 _S_(u16 v)
233{
234 u16 t = Sbox[Hi8(v)];
235 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
236}
237
238#define PHASE1_LOOP_COUNT 8
239
240static void tkip_mixing_phase1(u16 * TTAK, const u8 * TK, const u8 * TA,
241 u32 IV32)
242{
243 int i, j;
244
245 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
246 TTAK[0] = Lo16(IV32);
247 TTAK[1] = Hi16(IV32);
248 TTAK[2] = Mk16(TA[1], TA[0]);
249 TTAK[3] = Mk16(TA[3], TA[2]);
250 TTAK[4] = Mk16(TA[5], TA[4]);
251
252 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
253 j = 2 * (i & 1);
254 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
255 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
256 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
257 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
258 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
259 }
260}
261
262static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
263 u16 IV16)
264{
265 /* Make temporary area overlap WEP seed so that the final copy can be
266 * avoided on little endian hosts. */
267 u16 *PPK = (u16 *) & WEPSeed[4];
268
269 /* Step 1 - make copy of TTAK and bring in TSC */
270 PPK[0] = TTAK[0];
271 PPK[1] = TTAK[1];
272 PPK[2] = TTAK[2];
273 PPK[3] = TTAK[3];
274 PPK[4] = TTAK[4];
275 PPK[5] = TTAK[4] + IV16;
276
277 /* Step 2 - 96-bit bijective mixing using S-box */
278 PPK[0] += _S_(PPK[5] ^ Mk16_le((__le16 *) & TK[0]));
279 PPK[1] += _S_(PPK[0] ^ Mk16_le((__le16 *) & TK[2]));
280 PPK[2] += _S_(PPK[1] ^ Mk16_le((__le16 *) & TK[4]));
281 PPK[3] += _S_(PPK[2] ^ Mk16_le((__le16 *) & TK[6]));
282 PPK[4] += _S_(PPK[3] ^ Mk16_le((__le16 *) & TK[8]));
283 PPK[5] += _S_(PPK[4] ^ Mk16_le((__le16 *) & TK[10]));
284
285 PPK[0] += RotR1(PPK[5] ^ Mk16_le((__le16 *) & TK[12]));
286 PPK[1] += RotR1(PPK[0] ^ Mk16_le((__le16 *) & TK[14]));
287 PPK[2] += RotR1(PPK[1]);
288 PPK[3] += RotR1(PPK[2]);
289 PPK[4] += RotR1(PPK[3]);
290 PPK[5] += RotR1(PPK[4]);
291
292 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
293 * WEPSeed[0..2] is transmitted as WEP IV */
294 WEPSeed[0] = Hi8(IV16);
295 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
296 WEPSeed[2] = Lo8(IV16);
297 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((__le16 *) & TK[0])) >> 1);
298
299#ifdef __BIG_ENDIAN
300 {
301 int i;
302 for (i = 0; i < 6; i++)
303 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
304 }
305#endif
306}
307
308static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
309 u8 * rc4key, int keylen, void *priv)
310{
311 struct ieee80211_tkip_data *tkey = priv;
312 int len;
313 u8 *pos;
314 struct ieee80211_hdr_4addr *hdr;
315
316 hdr = (struct ieee80211_hdr_4addr *)skb->data;
317
318 if (skb_headroom(skb) < 8 || skb->len < hdr_len)
319 return -1;
320
321 if (rc4key == NULL || keylen < 16)
322 return -1;
323
324 if (!tkey->tx_phase1_done) {
325 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
326 tkey->tx_iv32);
327 tkey->tx_phase1_done = 1;
328 }
329 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
330
331 len = skb->len - hdr_len;
332 pos = skb_push(skb, 8);
333 memmove(pos, pos + 8, hdr_len);
334 pos += hdr_len;
335
336 *pos++ = *rc4key;
337 *pos++ = *(rc4key + 1);
338 *pos++ = *(rc4key + 2);
339 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
340 *pos++ = tkey->tx_iv32 & 0xff;
341 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
342 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
343 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
344
345 tkey->tx_iv16++;
346 if (tkey->tx_iv16 == 0) {
347 tkey->tx_phase1_done = 0;
348 tkey->tx_iv32++;
349 }
350
351 return 8;
352}
353
354static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
355{
356 struct ieee80211_tkip_data *tkey = priv;
357 struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
358 int len;
359 u8 rc4key[16], *pos, *icv;
360 u32 crc;
361 struct scatterlist sg;
362 DECLARE_MAC_BUF(mac);
363
364 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
365 if (net_ratelimit()) {
366 struct ieee80211_hdr_4addr *hdr =
367 (struct ieee80211_hdr_4addr *)skb->data;
368 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
369 "TX packet to %s\n",
370 print_mac(mac, hdr->addr1));
371 }
372 return -1;
373 }
374
375 if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
376 return -1;
377
378 len = skb->len - hdr_len;
379 pos = skb->data + hdr_len;
380
381 if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
382 return -1;
383
384 icv = skb_put(skb, 4);
385
386 crc = ~crc32_le(~0, pos, len);
387 icv[0] = crc;
388 icv[1] = crc >> 8;
389 icv[2] = crc >> 16;
390 icv[3] = crc >> 24;
391
392 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
393 sg_init_one(&sg, pos, len + 4);
394 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
395}
396
397/*
398 * deal with seq counter wrapping correctly.
399 * refer to timer_after() for jiffies wrapping handling
400 */
401static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
402 u32 iv32_o, u16 iv16_o)
403{
404 if ((s32)iv32_n - (s32)iv32_o < 0 ||
405 (iv32_n == iv32_o && iv16_n <= iv16_o))
406 return 1;
407 return 0;
408}
409
410static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
411{
412 struct ieee80211_tkip_data *tkey = priv;
413 struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
414 u8 rc4key[16];
415 u8 keyidx, *pos;
416 u32 iv32;
417 u16 iv16;
418 struct ieee80211_hdr_4addr *hdr;
419 u8 icv[4];
420 u32 crc;
421 struct scatterlist sg;
422 int plen;
423 DECLARE_MAC_BUF(mac);
424
425 hdr = (struct ieee80211_hdr_4addr *)skb->data;
426
427 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
428 if (net_ratelimit()) {
429 printk(KERN_DEBUG ": TKIP countermeasures: dropped "
430 "received packet from %s\n",
431 print_mac(mac, hdr->addr2));
432 }
433 return -1;
434 }
435
436 if (skb->len < hdr_len + 8 + 4)
437 return -1;
438
439 pos = skb->data + hdr_len;
440 keyidx = pos[3];
441 if (!(keyidx & (1 << 5))) {
442 if (net_ratelimit()) {
443 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
444 " flag from %s\n", print_mac(mac, hdr->addr2));
445 }
446 return -2;
447 }
448 keyidx >>= 6;
449 if (tkey->key_idx != keyidx) {
450 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
451 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
452 return -6;
453 }
454 if (!tkey->key_set) {
455 if (net_ratelimit()) {
456 printk(KERN_DEBUG "TKIP: received packet from %s"
457 " with keyid=%d that does not have a configured"
458 " key\n", print_mac(mac, hdr->addr2), keyidx);
459 }
460 return -3;
461 }
462 iv16 = (pos[0] << 8) | pos[2];
463 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
464 pos += 8;
465
466 if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
467 if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
468 IEEE80211_DEBUG_DROP("TKIP: replay detected: STA=%s"
469 " previous TSC %08x%04x received TSC "
470 "%08x%04x\n", print_mac(mac, hdr->addr2),
471 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
472 }
473 tkey->dot11RSNAStatsTKIPReplays++;
474 return -4;
475 }
476
477 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
478 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
479 tkey->rx_phase1_done = 1;
480 }
481 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
482
483 plen = skb->len - hdr_len - 12;
484
485 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
486 sg_init_one(&sg, pos, plen + 4);
487 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
488 if (net_ratelimit()) {
489 printk(KERN_DEBUG ": TKIP: failed to decrypt "
490 "received packet from %s\n",
491 print_mac(mac, hdr->addr2));
492 }
493 return -7;
494 }
495
496 crc = ~crc32_le(~0, pos, plen);
497 icv[0] = crc;
498 icv[1] = crc >> 8;
499 icv[2] = crc >> 16;
500 icv[3] = crc >> 24;
501 if (memcmp(icv, pos + plen, 4) != 0) {
502 if (iv32 != tkey->rx_iv32) {
503 /* Previously cached Phase1 result was already lost, so
504 * it needs to be recalculated for the next packet. */
505 tkey->rx_phase1_done = 0;
506 }
507 if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) {
508 IEEE80211_DEBUG_DROP("TKIP: ICV error detected: STA="
509 "%s\n", print_mac(mac, hdr->addr2));
510 }
511 tkey->dot11RSNAStatsTKIPICVErrors++;
512 return -5;
513 }
514
515 /* Update real counters only after Michael MIC verification has
516 * completed */
517 tkey->rx_iv32_new = iv32;
518 tkey->rx_iv16_new = iv16;
519
520 /* Remove IV and ICV */
521 memmove(skb->data + 8, skb->data, hdr_len);
522 skb_pull(skb, 8);
523 skb_trim(skb, skb->len - 4);
524
525 return keyidx;
526}
527
528static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
529 u8 * data, size_t data_len, u8 * mic)
530{
531 struct hash_desc desc;
532 struct scatterlist sg[2];
533
534 if (tfm_michael == NULL) {
535 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
536 return -1;
537 }
538 sg_init_table(sg, 2);
539 sg_set_buf(&sg[0], hdr, 16);
540 sg_set_buf(&sg[1], data, data_len);
541
542 if (crypto_hash_setkey(tfm_michael, key, 8))
543 return -1;
544
545 desc.tfm = tfm_michael;
546 desc.flags = 0;
547 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
548}
549
550static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
551{
552 struct ieee80211_hdr_4addr *hdr11;
553 u16 stype;
554
555 hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
556 stype = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl));
557
558 switch (le16_to_cpu(hdr11->frame_ctl) &
559 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
560 case IEEE80211_FCTL_TODS:
561 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
562 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
563 break;
564 case IEEE80211_FCTL_FROMDS:
565 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
566 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
567 break;
568 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
569 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
570 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
571 break;
572 case 0:
573 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
574 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
575 break;
576 }
577
578 if (stype & IEEE80211_STYPE_QOS_DATA) {
579 const struct ieee80211_hdr_3addrqos *qoshdr =
580 (struct ieee80211_hdr_3addrqos *)skb->data;
581 hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
582 } else
583 hdr[12] = 0; /* priority */
584
585 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
586}
587
588static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
589 void *priv)
590{
591 struct ieee80211_tkip_data *tkey = priv;
592 u8 *pos;
593
594 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
595 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
596 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
597 skb_tailroom(skb), hdr_len, skb->len);
598 return -1;
599 }
600
601 michael_mic_hdr(skb, tkey->tx_hdr);
602 pos = skb_put(skb, 8);
603 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
604 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
605 return -1;
606
607 return 0;
608}
609
610static void ieee80211_michael_mic_failure(struct net_device *dev,
611 struct ieee80211_hdr_4addr *hdr,
612 int keyidx)
613{
614 union iwreq_data wrqu;
615 struct iw_michaelmicfailure ev;
616
617 /* TODO: needed parameters: count, keyid, key type, TSC */
618 memset(&ev, 0, sizeof(ev));
619 ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
620 if (hdr->addr1[0] & 0x01)
621 ev.flags |= IW_MICFAILURE_GROUP;
622 else
623 ev.flags |= IW_MICFAILURE_PAIRWISE;
624 ev.src_addr.sa_family = ARPHRD_ETHER;
625 memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
626 memset(&wrqu, 0, sizeof(wrqu));
627 wrqu.data.length = sizeof(ev);
628 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
629}
630
631static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
632 int hdr_len, void *priv)
633{
634 struct ieee80211_tkip_data *tkey = priv;
635 u8 mic[8];
636 DECLARE_MAC_BUF(mac);
637
638 if (!tkey->key_set)
639 return -1;
640
641 michael_mic_hdr(skb, tkey->rx_hdr);
642 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
643 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
644 return -1;
645 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
646 struct ieee80211_hdr_4addr *hdr;
647 hdr = (struct ieee80211_hdr_4addr *)skb->data;
648 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
649 "MSDU from %s keyidx=%d\n",
650 skb->dev ? skb->dev->name : "N/A", print_mac(mac, hdr->addr2),
651 keyidx);
652 if (skb->dev)
653 ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
654 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
655 return -1;
656 }
657
658 /* Update TSC counters for RX now that the packet verification has
659 * completed. */
660 tkey->rx_iv32 = tkey->rx_iv32_new;
661 tkey->rx_iv16 = tkey->rx_iv16_new;
662
663 skb_trim(skb, skb->len - 8);
664
665 return 0;
666}
667
668static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
669{
670 struct ieee80211_tkip_data *tkey = priv;
671 int keyidx;
672 struct crypto_hash *tfm = tkey->tx_tfm_michael;
673 struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
674 struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
675 struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
676
677 keyidx = tkey->key_idx;
678 memset(tkey, 0, sizeof(*tkey));
679 tkey->key_idx = keyidx;
680 tkey->tx_tfm_michael = tfm;
681 tkey->tx_tfm_arc4 = tfm2;
682 tkey->rx_tfm_michael = tfm3;
683 tkey->rx_tfm_arc4 = tfm4;
684 if (len == TKIP_KEY_LEN) {
685 memcpy(tkey->key, key, TKIP_KEY_LEN);
686 tkey->key_set = 1;
687 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
688 if (seq) {
689 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
690 (seq[3] << 8) | seq[2];
691 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
692 }
693 } else if (len == 0)
694 tkey->key_set = 0;
695 else
696 return -1;
697
698 return 0;
699}
700
701static int ieee80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
702{
703 struct ieee80211_tkip_data *tkey = priv;
704
705 if (len < TKIP_KEY_LEN)
706 return -1;
707
708 if (!tkey->key_set)
709 return 0;
710 memcpy(key, tkey->key, TKIP_KEY_LEN);
711
712 if (seq) {
713 /* Return the sequence number of the last transmitted frame. */
714 u16 iv16 = tkey->tx_iv16;
715 u32 iv32 = tkey->tx_iv32;
716 if (iv16 == 0)
717 iv32--;
718 iv16--;
719 seq[0] = tkey->tx_iv16;
720 seq[1] = tkey->tx_iv16 >> 8;
721 seq[2] = tkey->tx_iv32;
722 seq[3] = tkey->tx_iv32 >> 8;
723 seq[4] = tkey->tx_iv32 >> 16;
724 seq[5] = tkey->tx_iv32 >> 24;
725 }
726
727 return TKIP_KEY_LEN;
728}
729
730static char *ieee80211_tkip_print_stats(char *p, void *priv)
731{
732 struct ieee80211_tkip_data *tkip = priv;
733 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
734 "tx_pn=%02x%02x%02x%02x%02x%02x "
735 "rx_pn=%02x%02x%02x%02x%02x%02x "
736 "replays=%d icv_errors=%d local_mic_failures=%d\n",
737 tkip->key_idx, tkip->key_set,
738 (tkip->tx_iv32 >> 24) & 0xff,
739 (tkip->tx_iv32 >> 16) & 0xff,
740 (tkip->tx_iv32 >> 8) & 0xff,
741 tkip->tx_iv32 & 0xff,
742 (tkip->tx_iv16 >> 8) & 0xff,
743 tkip->tx_iv16 & 0xff,
744 (tkip->rx_iv32 >> 24) & 0xff,
745 (tkip->rx_iv32 >> 16) & 0xff,
746 (tkip->rx_iv32 >> 8) & 0xff,
747 tkip->rx_iv32 & 0xff,
748 (tkip->rx_iv16 >> 8) & 0xff,
749 tkip->rx_iv16 & 0xff,
750 tkip->dot11RSNAStatsTKIPReplays,
751 tkip->dot11RSNAStatsTKIPICVErrors,
752 tkip->dot11RSNAStatsTKIPLocalMICFailures);
753 return p;
754}
755
756static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
757 .name = "TKIP",
758 .init = ieee80211_tkip_init,
759 .deinit = ieee80211_tkip_deinit,
760 .build_iv = ieee80211_tkip_hdr,
761 .encrypt_mpdu = ieee80211_tkip_encrypt,
762 .decrypt_mpdu = ieee80211_tkip_decrypt,
763 .encrypt_msdu = ieee80211_michael_mic_add,
764 .decrypt_msdu = ieee80211_michael_mic_verify,
765 .set_key = ieee80211_tkip_set_key,
766 .get_key = ieee80211_tkip_get_key,
767 .print_stats = ieee80211_tkip_print_stats,
768 .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
769 .extra_mpdu_postfix_len = 4, /* ICV */
770 .extra_msdu_postfix_len = 8, /* MIC */
771 .get_flags = ieee80211_tkip_get_flags,
772 .set_flags = ieee80211_tkip_set_flags,
773 .owner = THIS_MODULE,
774};
775
776static int __init ieee80211_crypto_tkip_init(void)
777{
778 return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
779}
780
781static void __exit ieee80211_crypto_tkip_exit(void)
782{
783 ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
784}
785
786module_init(ieee80211_crypto_tkip_init);
787module_exit(ieee80211_crypto_tkip_exit);
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
deleted file mode 100644
index 3fa30c40779f..000000000000
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ /dev/null
@@ -1,295 +0,0 @@
1/*
2 * Host AP crypt: host-based WEP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/err.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/random.h>
17#include <linux/scatterlist.h>
18#include <linux/skbuff.h>
19#include <linux/mm.h>
20#include <asm/string.h>
21
22#include <net/ieee80211.h>
23
24#include <linux/crypto.h>
25#include <linux/crc32.h>
26
27MODULE_AUTHOR("Jouni Malinen");
28MODULE_DESCRIPTION("Host AP crypt: WEP");
29MODULE_LICENSE("GPL");
30
31struct prism2_wep_data {
32 u32 iv;
33#define WEP_KEY_LEN 13
34 u8 key[WEP_KEY_LEN + 1];
35 u8 key_len;
36 u8 key_idx;
37 struct crypto_blkcipher *tx_tfm;
38 struct crypto_blkcipher *rx_tfm;
39};
40
41static void *prism2_wep_init(int keyidx)
42{
43 struct prism2_wep_data *priv;
44
45 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
46 if (priv == NULL)
47 goto fail;
48 priv->key_idx = keyidx;
49
50 priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
51 if (IS_ERR(priv->tx_tfm)) {
52 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
53 "crypto API arc4\n");
54 priv->tx_tfm = NULL;
55 goto fail;
56 }
57
58 priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
59 if (IS_ERR(priv->rx_tfm)) {
60 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
61 "crypto API arc4\n");
62 priv->rx_tfm = NULL;
63 goto fail;
64 }
65 /* start WEP IV from a random value */
66 get_random_bytes(&priv->iv, 4);
67
68 return priv;
69
70 fail:
71 if (priv) {
72 if (priv->tx_tfm)
73 crypto_free_blkcipher(priv->tx_tfm);
74 if (priv->rx_tfm)
75 crypto_free_blkcipher(priv->rx_tfm);
76 kfree(priv);
77 }
78 return NULL;
79}
80
81static void prism2_wep_deinit(void *priv)
82{
83 struct prism2_wep_data *_priv = priv;
84 if (_priv) {
85 if (_priv->tx_tfm)
86 crypto_free_blkcipher(_priv->tx_tfm);
87 if (_priv->rx_tfm)
88 crypto_free_blkcipher(_priv->rx_tfm);
89 }
90 kfree(priv);
91}
92
93/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
94static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
95 u8 *key, int keylen, void *priv)
96{
97 struct prism2_wep_data *wep = priv;
98 u32 klen, len;
99 u8 *pos;
100
101 if (skb_headroom(skb) < 4 || skb->len < hdr_len)
102 return -1;
103
104 len = skb->len - hdr_len;
105 pos = skb_push(skb, 4);
106 memmove(pos, pos + 4, hdr_len);
107 pos += hdr_len;
108
109 klen = 3 + wep->key_len;
110
111 wep->iv++;
112
113 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
114 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
115 * can be used to speedup attacks, so avoid using them. */
116 if ((wep->iv & 0xff00) == 0xff00) {
117 u8 B = (wep->iv >> 16) & 0xff;
118 if (B >= 3 && B < klen)
119 wep->iv += 0x0100;
120 }
121
122 /* Prepend 24-bit IV to RC4 key and TX frame */
123 *pos++ = (wep->iv >> 16) & 0xff;
124 *pos++ = (wep->iv >> 8) & 0xff;
125 *pos++ = wep->iv & 0xff;
126 *pos++ = wep->key_idx << 6;
127
128 return 0;
129}
130
131/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
132 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
133 * so the payload length increases with 8 bytes.
134 *
135 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
136 */
137static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
138{
139 struct prism2_wep_data *wep = priv;
140 struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
141 u32 crc, klen, len;
142 u8 *pos, *icv;
143 struct scatterlist sg;
144 u8 key[WEP_KEY_LEN + 3];
145
146 /* other checks are in prism2_wep_build_iv */
147 if (skb_tailroom(skb) < 4)
148 return -1;
149
150 /* add the IV to the frame */
151 if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))
152 return -1;
153
154 /* Copy the IV into the first 3 bytes of the key */
155 skb_copy_from_linear_data_offset(skb, hdr_len, key, 3);
156
157 /* Copy rest of the WEP key (the secret part) */
158 memcpy(key + 3, wep->key, wep->key_len);
159
160 len = skb->len - hdr_len - 4;
161 pos = skb->data + hdr_len + 4;
162 klen = 3 + wep->key_len;
163
164 /* Append little-endian CRC32 over only the data and encrypt it to produce ICV */
165 crc = ~crc32_le(~0, pos, len);
166 icv = skb_put(skb, 4);
167 icv[0] = crc;
168 icv[1] = crc >> 8;
169 icv[2] = crc >> 16;
170 icv[3] = crc >> 24;
171
172 crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
173 sg_init_one(&sg, pos, len + 4);
174 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
175}
176
177/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
178 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
179 * ICV (4 bytes). len includes both IV and ICV.
180 *
181 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
182 * failure. If frame is OK, IV and ICV will be removed.
183 */
184static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
185{
186 struct prism2_wep_data *wep = priv;
187 struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
188 u32 crc, klen, plen;
189 u8 key[WEP_KEY_LEN + 3];
190 u8 keyidx, *pos, icv[4];
191 struct scatterlist sg;
192
193 if (skb->len < hdr_len + 8)
194 return -1;
195
196 pos = skb->data + hdr_len;
197 key[0] = *pos++;
198 key[1] = *pos++;
199 key[2] = *pos++;
200 keyidx = *pos++ >> 6;
201 if (keyidx != wep->key_idx)
202 return -1;
203
204 klen = 3 + wep->key_len;
205
206 /* Copy rest of the WEP key (the secret part) */
207 memcpy(key + 3, wep->key, wep->key_len);
208
209 /* Apply RC4 to data and compute CRC32 over decrypted data */
210 plen = skb->len - hdr_len - 8;
211
212 crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
213 sg_init_one(&sg, pos, plen + 4);
214 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
215 return -7;
216
217 crc = ~crc32_le(~0, pos, plen);
218 icv[0] = crc;
219 icv[1] = crc >> 8;
220 icv[2] = crc >> 16;
221 icv[3] = crc >> 24;
222 if (memcmp(icv, pos + plen, 4) != 0) {
223 /* ICV mismatch - drop frame */
224 return -2;
225 }
226
227 /* Remove IV and ICV */
228 memmove(skb->data + 4, skb->data, hdr_len);
229 skb_pull(skb, 4);
230 skb_trim(skb, skb->len - 4);
231
232 return 0;
233}
234
235static int prism2_wep_set_key(void *key, int len, u8 * seq, void *priv)
236{
237 struct prism2_wep_data *wep = priv;
238
239 if (len < 0 || len > WEP_KEY_LEN)
240 return -1;
241
242 memcpy(wep->key, key, len);
243 wep->key_len = len;
244
245 return 0;
246}
247
248static int prism2_wep_get_key(void *key, int len, u8 * seq, void *priv)
249{
250 struct prism2_wep_data *wep = priv;
251
252 if (len < wep->key_len)
253 return -1;
254
255 memcpy(key, wep->key, wep->key_len);
256
257 return wep->key_len;
258}
259
260static char *prism2_wep_print_stats(char *p, void *priv)
261{
262 struct prism2_wep_data *wep = priv;
263 p += sprintf(p, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
264 return p;
265}
266
267static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
268 .name = "WEP",
269 .init = prism2_wep_init,
270 .deinit = prism2_wep_deinit,
271 .build_iv = prism2_wep_build_iv,
272 .encrypt_mpdu = prism2_wep_encrypt,
273 .decrypt_mpdu = prism2_wep_decrypt,
274 .encrypt_msdu = NULL,
275 .decrypt_msdu = NULL,
276 .set_key = prism2_wep_set_key,
277 .get_key = prism2_wep_get_key,
278 .print_stats = prism2_wep_print_stats,
279 .extra_mpdu_prefix_len = 4, /* IV */
280 .extra_mpdu_postfix_len = 4, /* ICV */
281 .owner = THIS_MODULE,
282};
283
284static int __init ieee80211_crypto_wep_init(void)
285{
286 return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
287}
288
289static void __exit ieee80211_crypto_wep_exit(void)
290{
291 ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
292}
293
294module_init(ieee80211_crypto_wep_init);
295module_exit(ieee80211_crypto_wep_exit);
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
deleted file mode 100644
index 960ad13f5e9f..000000000000
--- a/net/ieee80211/ieee80211_geo.c
+++ /dev/null
@@ -1,195 +0,0 @@
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/errno.h>
28#include <linux/if_arp.h>
29#include <linux/in6.h>
30#include <linux/in.h>
31#include <linux/ip.h>
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/netdevice.h>
35#include <linux/proc_fs.h>
36#include <linux/skbuff.h>
37#include <linux/slab.h>
38#include <linux/tcp.h>
39#include <linux/types.h>
40#include <linux/wireless.h>
41#include <linux/etherdevice.h>
42#include <asm/uaccess.h>
43
44#include <net/ieee80211.h>
45
46int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
47{
48 int i;
49
50 /* Driver needs to initialize the geography map before using
51 * these helper functions */
52 if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
53 return 0;
54
55 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
56 for (i = 0; i < ieee->geo.bg_channels; i++)
57 /* NOTE: If G mode is currently supported but
58 * this is a B only channel, we don't see it
59 * as valid. */
60 if ((ieee->geo.bg[i].channel == channel) &&
61 !(ieee->geo.bg[i].flags & IEEE80211_CH_INVALID) &&
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 !(ieee->geo.a[i].flags & IEEE80211_CH_INVALID))
70 return IEEE80211_52GHZ_BAND;
71
72 return 0;
73}
74
75int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
76{
77 int i;
78
79 /* Driver needs to initialize the geography map before using
80 * these helper functions */
81 if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
82 return -1;
83
84 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
85 for (i = 0; i < ieee->geo.bg_channels; i++)
86 if (ieee->geo.bg[i].channel == channel)
87 return i;
88
89 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
90 for (i = 0; i < ieee->geo.a_channels; i++)
91 if (ieee->geo.a[i].channel == channel)
92 return i;
93
94 return -1;
95}
96
97u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, u8 channel)
98{
99 const struct ieee80211_channel * ch;
100
101 /* Driver needs to initialize the geography map before using
102 * these helper functions */
103 if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
104 return 0;
105
106 ch = ieee80211_get_channel(ieee, channel);
107 if (!ch->channel)
108 return 0;
109 return ch->freq;
110}
111
112u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
113{
114 int i;
115
116 /* Driver needs to initialize the geography map before using
117 * these helper functions */
118 if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
119 return 0;
120
121 freq /= 100000;
122
123 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
124 for (i = 0; i < ieee->geo.bg_channels; i++)
125 if (ieee->geo.bg[i].freq == freq)
126 return ieee->geo.bg[i].channel;
127
128 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
129 for (i = 0; i < ieee->geo.a_channels; i++)
130 if (ieee->geo.a[i].freq == freq)
131 return ieee->geo.a[i].channel;
132
133 return 0;
134}
135
136int ieee80211_set_geo(struct ieee80211_device *ieee,
137 const struct ieee80211_geo *geo)
138{
139 memcpy(ieee->geo.name, geo->name, 3);
140 ieee->geo.name[3] = '\0';
141 ieee->geo.bg_channels = geo->bg_channels;
142 ieee->geo.a_channels = geo->a_channels;
143 memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
144 sizeof(struct ieee80211_channel));
145 memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
146 sizeof(struct ieee80211_channel));
147 return 0;
148}
149
150const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
151{
152 return &ieee->geo;
153}
154
155u8 ieee80211_get_channel_flags(struct ieee80211_device * ieee, u8 channel)
156{
157 int index = ieee80211_channel_to_index(ieee, channel);
158
159 if (index == -1)
160 return IEEE80211_CH_INVALID;
161
162 if (channel <= IEEE80211_24GHZ_CHANNELS)
163 return ieee->geo.bg[index].flags;
164
165 return ieee->geo.a[index].flags;
166}
167
168static const struct ieee80211_channel bad_channel = {
169 .channel = 0,
170 .flags = IEEE80211_CH_INVALID,
171 .max_power = 0,
172};
173
174const struct ieee80211_channel *ieee80211_get_channel(struct ieee80211_device
175 *ieee, u8 channel)
176{
177 int index = ieee80211_channel_to_index(ieee, channel);
178
179 if (index == -1)
180 return &bad_channel;
181
182 if (channel <= IEEE80211_24GHZ_CHANNELS)
183 return &ieee->geo.bg[index];
184
185 return &ieee->geo.a[index];
186}
187
188EXPORT_SYMBOL(ieee80211_get_channel);
189EXPORT_SYMBOL(ieee80211_get_channel_flags);
190EXPORT_SYMBOL(ieee80211_is_valid_channel);
191EXPORT_SYMBOL(ieee80211_freq_to_channel);
192EXPORT_SYMBOL(ieee80211_channel_to_freq);
193EXPORT_SYMBOL(ieee80211_channel_to_index);
194EXPORT_SYMBOL(ieee80211_set_geo);
195EXPORT_SYMBOL(ieee80211_get_geo);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
deleted file mode 100644
index 949772a5a7dc..000000000000
--- a/net/ieee80211/ieee80211_module.c
+++ /dev/null
@@ -1,338 +0,0 @@
1/*******************************************************************************
2
3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <j@w1.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31*******************************************************************************/
32
33#include <linux/compiler.h>
34#include <linux/errno.h>
35#include <linux/if_arp.h>
36#include <linux/in6.h>
37#include <linux/in.h>
38#include <linux/ip.h>
39#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/netdevice.h>
42#include <linux/proc_fs.h>
43#include <linux/skbuff.h>
44#include <linux/slab.h>
45#include <linux/tcp.h>
46#include <linux/types.h>
47#include <linux/wireless.h>
48#include <linux/etherdevice.h>
49#include <asm/uaccess.h>
50#include <net/net_namespace.h>
51#include <net/arp.h>
52
53#include <net/ieee80211.h>
54
55#define DRV_DESCRIPTION "802.11 data/management/control stack"
56#define DRV_NAME "ieee80211"
57#define DRV_VERSION IEEE80211_VERSION
58#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
59
60MODULE_VERSION(DRV_VERSION);
61MODULE_DESCRIPTION(DRV_DESCRIPTION);
62MODULE_AUTHOR(DRV_COPYRIGHT);
63MODULE_LICENSE("GPL");
64
65static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
66{
67 if (ieee->networks)
68 return 0;
69
70 ieee->networks =
71 kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
72 GFP_KERNEL);
73 if (!ieee->networks) {
74 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
75 ieee->dev->name);
76 return -ENOMEM;
77 }
78
79 return 0;
80}
81
82void ieee80211_network_reset(struct ieee80211_network *network)
83{
84 if (!network)
85 return;
86
87 if (network->ibss_dfs) {
88 kfree(network->ibss_dfs);
89 network->ibss_dfs = NULL;
90 }
91}
92
93static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
94{
95 int i;
96
97 if (!ieee->networks)
98 return;
99
100 for (i = 0; i < MAX_NETWORK_COUNT; i++)
101 if (ieee->networks[i].ibss_dfs)
102 kfree(ieee->networks[i].ibss_dfs);
103
104 kfree(ieee->networks);
105 ieee->networks = NULL;
106}
107
108static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
109{
110 int i;
111
112 INIT_LIST_HEAD(&ieee->network_free_list);
113 INIT_LIST_HEAD(&ieee->network_list);
114 for (i = 0; i < MAX_NETWORK_COUNT; i++)
115 list_add_tail(&ieee->networks[i].list,
116 &ieee->network_free_list);
117}
118
119static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
120{
121 if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN))
122 return -EINVAL;
123 dev->mtu = new_mtu;
124 return 0;
125}
126
127static struct net_device_stats *ieee80211_generic_get_stats(
128 struct net_device *dev)
129{
130 struct ieee80211_device *ieee = netdev_priv(dev);
131 return &ieee->stats;
132}
133
134struct net_device *alloc_ieee80211(int sizeof_priv)
135{
136 struct ieee80211_device *ieee;
137 struct net_device *dev;
138 int err;
139
140 IEEE80211_DEBUG_INFO("Initializing...\n");
141
142 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
143 if (!dev) {
144 IEEE80211_ERROR("Unable to allocate network device.\n");
145 goto failed;
146 }
147 ieee = netdev_priv(dev);
148 dev->hard_start_xmit = ieee80211_xmit;
149 dev->change_mtu = ieee80211_change_mtu;
150
151 /* Drivers are free to override this if the generic implementation
152 * does not meet their needs. */
153 dev->get_stats = ieee80211_generic_get_stats;
154
155 ieee->dev = dev;
156
157 err = ieee80211_networks_allocate(ieee);
158 if (err) {
159 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
160 goto failed_free_netdev;
161 }
162 ieee80211_networks_initialize(ieee);
163
164 /* Default fragmentation threshold is maximum payload size */
165 ieee->fts = DEFAULT_FTS;
166 ieee->rts = DEFAULT_FTS;
167 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
168 ieee->open_wep = 1;
169
170 /* Default to enabling full open WEP with host based encrypt/decrypt */
171 ieee->host_encrypt = 1;
172 ieee->host_decrypt = 1;
173 ieee->host_mc_decrypt = 1;
174
175 /* Host fragementation in Open mode. Default is enabled.
176 * Note: host fragmentation is always enabled if host encryption
177 * is enabled. For cards can do hardware encryption, they must do
178 * hardware fragmentation as well. So we don't need a variable
179 * like host_enc_frag. */
180 ieee->host_open_frag = 1;
181 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
182
183 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
184 setup_timer(&ieee->crypt_deinit_timer, ieee80211_crypt_deinit_handler,
185 (unsigned long)ieee);
186 ieee->crypt_quiesced = 0;
187
188 spin_lock_init(&ieee->lock);
189
190 ieee->wpa_enabled = 0;
191 ieee->drop_unencrypted = 0;
192 ieee->privacy_invoked = 0;
193
194 return dev;
195
196failed_free_netdev:
197 free_netdev(dev);
198failed:
199 return NULL;
200}
201
202void free_ieee80211(struct net_device *dev)
203{
204 struct ieee80211_device *ieee = netdev_priv(dev);
205
206 int i;
207
208 ieee80211_crypt_quiescing(ieee);
209 del_timer_sync(&ieee->crypt_deinit_timer);
210 ieee80211_crypt_deinit_entries(ieee, 1);
211
212 for (i = 0; i < WEP_KEYS; i++) {
213 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
214 if (crypt) {
215 if (crypt->ops) {
216 crypt->ops->deinit(crypt->priv);
217 module_put(crypt->ops->owner);
218 }
219 kfree(crypt);
220 ieee->crypt[i] = NULL;
221 }
222 }
223
224 ieee80211_networks_free(ieee);
225 free_netdev(dev);
226}
227
228#ifdef CONFIG_IEEE80211_DEBUG
229
230static int debug = 0;
231u32 ieee80211_debug_level = 0;
232EXPORT_SYMBOL_GPL(ieee80211_debug_level);
233static struct proc_dir_entry *ieee80211_proc = NULL;
234
235static int show_debug_level(char *page, char **start, off_t offset,
236 int count, int *eof, void *data)
237{
238 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
239}
240
241static int store_debug_level(struct file *file, const char __user * buffer,
242 unsigned long count, void *data)
243{
244 char buf[] = "0x00000000\n";
245 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
246 unsigned long val;
247
248 if (copy_from_user(buf, buffer, len))
249 return count;
250 buf[len] = 0;
251 if (sscanf(buf, "%li", &val) != 1)
252 printk(KERN_INFO DRV_NAME
253 ": %s is not in hex or decimal form.\n", buf);
254 else
255 ieee80211_debug_level = val;
256
257 return strnlen(buf, len);
258}
259#endif /* CONFIG_IEEE80211_DEBUG */
260
261static int __init ieee80211_init(void)
262{
263#ifdef CONFIG_IEEE80211_DEBUG
264 struct proc_dir_entry *e;
265
266 ieee80211_debug_level = debug;
267 ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
268 if (ieee80211_proc == NULL) {
269 IEEE80211_ERROR("Unable to create " DRV_NAME
270 " proc directory\n");
271 return -EIO;
272 }
273 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
274 ieee80211_proc);
275 if (!e) {
276 remove_proc_entry(DRV_NAME, init_net.proc_net);
277 ieee80211_proc = NULL;
278 return -EIO;
279 }
280 e->read_proc = show_debug_level;
281 e->write_proc = store_debug_level;
282 e->data = NULL;
283#endif /* CONFIG_IEEE80211_DEBUG */
284
285 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
286 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
287
288 return 0;
289}
290
291static void __exit ieee80211_exit(void)
292{
293#ifdef CONFIG_IEEE80211_DEBUG
294 if (ieee80211_proc) {
295 remove_proc_entry("debug_level", ieee80211_proc);
296 remove_proc_entry(DRV_NAME, init_net.proc_net);
297 ieee80211_proc = NULL;
298 }
299#endif /* CONFIG_IEEE80211_DEBUG */
300}
301
302#ifdef CONFIG_IEEE80211_DEBUG
303#include <linux/moduleparam.h>
304module_param(debug, int, 0444);
305MODULE_PARM_DESC(debug, "debug output mask");
306#endif /* CONFIG_IEEE80211_DEBUG */
307
308module_exit(ieee80211_exit);
309module_init(ieee80211_init);
310
311const char *escape_essid(const char *essid, u8 essid_len)
312{
313 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
314 const char *s = essid;
315 char *d = escaped;
316
317 if (ieee80211_is_empty_essid(essid, essid_len)) {
318 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
319 return escaped;
320 }
321
322 essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
323 while (essid_len--) {
324 if (*s == '\0') {
325 *d++ = '\\';
326 *d++ = '0';
327 s++;
328 } else {
329 *d++ = *s++;
330 }
331 }
332 *d = '\0';
333 return escaped;
334}
335
336EXPORT_SYMBOL(alloc_ieee80211);
337EXPORT_SYMBOL(free_ieee80211);
338EXPORT_SYMBOL(escape_essid);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
deleted file mode 100644
index 69dbc342a464..000000000000
--- a/net/ieee80211/ieee80211_rx.c
+++ /dev/null
@@ -1,1831 +0,0 @@
1/*
2 * Original code based Host AP (software wireless LAN access point) driver
3 * for Intersil Prism2/2.5/3 - hostap.o module, common routines
4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <j@w1.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
8 * Copyright (c) 2004-2005, Intel Corporation
9 *
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
12 * published by the Free Software Foundation. See README and COPYING for
13 * more details.
14 */
15
16#include <linux/compiler.h>
17#include <linux/errno.h>
18#include <linux/if_arp.h>
19#include <linux/in6.h>
20#include <linux/in.h>
21#include <linux/ip.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/netdevice.h>
25#include <linux/proc_fs.h>
26#include <linux/skbuff.h>
27#include <linux/slab.h>
28#include <linux/tcp.h>
29#include <linux/types.h>
30#include <linux/wireless.h>
31#include <linux/etherdevice.h>
32#include <asm/uaccess.h>
33#include <linux/ctype.h>
34
35#include <net/ieee80211.h>
36
37static void ieee80211_monitor_rx(struct ieee80211_device *ieee,
38 struct sk_buff *skb,
39 struct ieee80211_rx_stats *rx_stats)
40{
41 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
42 u16 fc = le16_to_cpu(hdr->frame_ctl);
43
44 skb->dev = ieee->dev;
45 skb_reset_mac_header(skb);
46 skb_pull(skb, ieee80211_get_hdrlen(fc));
47 skb->pkt_type = PACKET_OTHERHOST;
48 skb->protocol = htons(ETH_P_80211_RAW);
49 memset(skb->cb, 0, sizeof(skb->cb));
50 netif_rx(skb);
51}
52
53/* Called only as a tasklet (software IRQ) */
54static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct
55 ieee80211_device
56 *ieee,
57 unsigned int seq,
58 unsigned int frag,
59 u8 * src,
60 u8 * dst)
61{
62 struct ieee80211_frag_entry *entry;
63 int i;
64
65 for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
66 entry = &ieee->frag_cache[i];
67 if (entry->skb != NULL &&
68 time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
69 IEEE80211_DEBUG_FRAG("expiring fragment cache entry "
70 "seq=%u last_frag=%u\n",
71 entry->seq, entry->last_frag);
72 dev_kfree_skb_any(entry->skb);
73 entry->skb = NULL;
74 }
75
76 if (entry->skb != NULL && entry->seq == seq &&
77 (entry->last_frag + 1 == frag || frag == -1) &&
78 !compare_ether_addr(entry->src_addr, src) &&
79 !compare_ether_addr(entry->dst_addr, dst))
80 return entry;
81 }
82
83 return NULL;
84}
85
86/* Called only as a tasklet (software IRQ) */
87static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
88 struct ieee80211_hdr_4addr *hdr)
89{
90 struct sk_buff *skb = NULL;
91 u16 sc;
92 unsigned int frag, seq;
93 struct ieee80211_frag_entry *entry;
94
95 sc = le16_to_cpu(hdr->seq_ctl);
96 frag = WLAN_GET_SEQ_FRAG(sc);
97 seq = WLAN_GET_SEQ_SEQ(sc);
98
99 if (frag == 0) {
100 /* Reserve enough space to fit maximum frame length */
101 skb = dev_alloc_skb(ieee->dev->mtu +
102 sizeof(struct ieee80211_hdr_4addr) +
103 8 /* LLC */ +
104 2 /* alignment */ +
105 8 /* WEP */ + ETH_ALEN /* WDS */ );
106 if (skb == NULL)
107 return NULL;
108
109 entry = &ieee->frag_cache[ieee->frag_next_idx];
110 ieee->frag_next_idx++;
111 if (ieee->frag_next_idx >= IEEE80211_FRAG_CACHE_LEN)
112 ieee->frag_next_idx = 0;
113
114 if (entry->skb != NULL)
115 dev_kfree_skb_any(entry->skb);
116
117 entry->first_frag_time = jiffies;
118 entry->seq = seq;
119 entry->last_frag = frag;
120 entry->skb = skb;
121 memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
122 memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
123 } else {
124 /* received a fragment of a frame for which the head fragment
125 * should have already been received */
126 entry = ieee80211_frag_cache_find(ieee, seq, frag, hdr->addr2,
127 hdr->addr1);
128 if (entry != NULL) {
129 entry->last_frag = frag;
130 skb = entry->skb;
131 }
132 }
133
134 return skb;
135}
136
137/* Called only as a tasklet (software IRQ) */
138static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
139 struct ieee80211_hdr_4addr *hdr)
140{
141 u16 sc;
142 unsigned int seq;
143 struct ieee80211_frag_entry *entry;
144
145 sc = le16_to_cpu(hdr->seq_ctl);
146 seq = WLAN_GET_SEQ_SEQ(sc);
147
148 entry = ieee80211_frag_cache_find(ieee, seq, -1, hdr->addr2,
149 hdr->addr1);
150
151 if (entry == NULL) {
152 IEEE80211_DEBUG_FRAG("could not invalidate fragment cache "
153 "entry (seq=%u)\n", seq);
154 return -1;
155 }
156
157 entry->skb = NULL;
158 return 0;
159}
160
161#ifdef NOT_YET
162/* ieee80211_rx_frame_mgtmt
163 *
164 * Responsible for handling management control frames
165 *
166 * Called by ieee80211_rx */
167static int
168ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
169 struct ieee80211_rx_stats *rx_stats, u16 type,
170 u16 stype)
171{
172 if (ieee->iw_mode == IW_MODE_MASTER) {
173 printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
174 ieee->dev->name);
175 return 0;
176/*
177 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
178 skb->data);*/
179 }
180
181 if (ieee->hostapd && type == WLAN_FC_TYPE_MGMT) {
182 if (stype == WLAN_FC_STYPE_BEACON &&
183 ieee->iw_mode == IW_MODE_MASTER) {
184 struct sk_buff *skb2;
185 /* Process beacon frames also in kernel driver to
186 * update STA(AP) table statistics */
187 skb2 = skb_clone(skb, GFP_ATOMIC);
188 if (skb2)
189 hostap_rx(skb2->dev, skb2, rx_stats);
190 }
191
192 /* send management frames to the user space daemon for
193 * processing */
194 ieee->apdevstats.rx_packets++;
195 ieee->apdevstats.rx_bytes += skb->len;
196 prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
197 return 0;
198 }
199
200 if (ieee->iw_mode == IW_MODE_MASTER) {
201 if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
202 printk(KERN_DEBUG "%s: unknown management frame "
203 "(type=0x%02x, stype=0x%02x) dropped\n",
204 skb->dev->name, type, stype);
205 return -1;
206 }
207
208 hostap_rx(skb->dev, skb, rx_stats);
209 return 0;
210 }
211
212 printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
213 "received in non-Host AP mode\n", skb->dev->name);
214 return -1;
215}
216#endif
217
218/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
219/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
220static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
221
222/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
223static unsigned char bridge_tunnel_header[] =
224 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
225/* No encapsulation header if EtherType < 0x600 (=length) */
226
227/* Called by ieee80211_rx_frame_decrypt */
228static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
229 struct sk_buff *skb)
230{
231 struct net_device *dev = ieee->dev;
232 u16 fc, ethertype;
233 struct ieee80211_hdr_3addr *hdr;
234 u8 *pos;
235
236 if (skb->len < 24)
237 return 0;
238
239 hdr = (struct ieee80211_hdr_3addr *)skb->data;
240 fc = le16_to_cpu(hdr->frame_ctl);
241
242 /* check that the frame is unicast frame to us */
243 if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
244 IEEE80211_FCTL_TODS &&
245 !compare_ether_addr(hdr->addr1, dev->dev_addr) &&
246 !compare_ether_addr(hdr->addr3, dev->dev_addr)) {
247 /* ToDS frame with own addr BSSID and DA */
248 } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
249 IEEE80211_FCTL_FROMDS &&
250 !compare_ether_addr(hdr->addr1, dev->dev_addr)) {
251 /* FromDS frame with own addr as DA */
252 } else
253 return 0;
254
255 if (skb->len < 24 + 8)
256 return 0;
257
258 /* check for port access entity Ethernet type */
259 pos = skb->data + 24;
260 ethertype = (pos[6] << 8) | pos[7];
261 if (ethertype == ETH_P_PAE)
262 return 1;
263
264 return 0;
265}
266
267/* Called only as a tasklet (software IRQ), by ieee80211_rx */
268static int
269ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
270 struct ieee80211_crypt_data *crypt)
271{
272 struct ieee80211_hdr_3addr *hdr;
273 int res, hdrlen;
274
275 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
276 return 0;
277
278 hdr = (struct ieee80211_hdr_3addr *)skb->data;
279 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
280
281 atomic_inc(&crypt->refcnt);
282 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
283 atomic_dec(&crypt->refcnt);
284 if (res < 0) {
285 IEEE80211_DEBUG_DROP("decryption failed (SA=" MAC_FMT
286 ") res=%d\n",
287 hdr->addr2[0], hdr->addr2[1],
288 hdr->addr2[2], hdr->addr2[3],
289 hdr->addr2[4], hdr->addr2[5],
290 res);
291 if (res == -2)
292 IEEE80211_DEBUG_DROP("Decryption failed ICV "
293 "mismatch (key %d)\n",
294 skb->data[hdrlen + 3] >> 6);
295 ieee->ieee_stats.rx_discards_undecryptable++;
296 return -1;
297 }
298
299 return res;
300}
301
302/* Called only as a tasklet (software IRQ), by ieee80211_rx */
303static int
304ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
305 struct sk_buff *skb, int keyidx,
306 struct ieee80211_crypt_data *crypt)
307{
308 struct ieee80211_hdr_3addr *hdr;
309 int res, hdrlen;
310
311 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
312 return 0;
313
314 hdr = (struct ieee80211_hdr_3addr *)skb->data;
315 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
316
317 atomic_inc(&crypt->refcnt);
318 res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
319 atomic_dec(&crypt->refcnt);
320 if (res < 0) {
321 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
322 " (SA=" MAC_FMT " keyidx=%d)\n",
323 ieee->dev->name,
324 hdr->addr2[0], hdr->addr2[1],
325 hdr->addr2[2], hdr->addr2[3],
326 hdr->addr2[4], hdr->addr2[5],
327 keyidx);
328 return -1;
329 }
330
331 return 0;
332}
333
334/* All received frames are sent to this function. @skb contains the frame in
335 * IEEE 802.11 format, i.e., in the format it was sent over air.
336 * This function is called only as a tasklet (software IRQ). */
337int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
338 struct ieee80211_rx_stats *rx_stats)
339{
340 struct net_device *dev = ieee->dev;
341 struct ieee80211_hdr_4addr *hdr;
342 size_t hdrlen;
343 u16 fc, type, stype, sc;
344 struct net_device_stats *stats;
345 unsigned int frag;
346 u8 *payload;
347 u16 ethertype;
348#ifdef NOT_YET
349 struct net_device *wds = NULL;
350 struct sk_buff *skb2 = NULL;
351 struct net_device *wds = NULL;
352 int frame_authorized = 0;
353 int from_assoc_ap = 0;
354 void *sta = NULL;
355#endif
356 u8 dst[ETH_ALEN];
357 u8 src[ETH_ALEN];
358 struct ieee80211_crypt_data *crypt = NULL;
359 int keyidx = 0;
360 int can_be_decrypted = 0;
361 DECLARE_MAC_BUF(mac);
362
363 hdr = (struct ieee80211_hdr_4addr *)skb->data;
364 stats = &ieee->stats;
365
366 if (skb->len < 10) {
367 printk(KERN_INFO "%s: SKB length < 10\n", dev->name);
368 goto rx_dropped;
369 }
370
371 fc = le16_to_cpu(hdr->frame_ctl);
372 type = WLAN_FC_GET_TYPE(fc);
373 stype = WLAN_FC_GET_STYPE(fc);
374 sc = le16_to_cpu(hdr->seq_ctl);
375 frag = WLAN_GET_SEQ_FRAG(sc);
376 hdrlen = ieee80211_get_hdrlen(fc);
377
378 if (skb->len < hdrlen) {
379 printk(KERN_INFO "%s: invalid SKB length %d\n",
380 dev->name, skb->len);
381 goto rx_dropped;
382 }
383
384 /* Put this code here so that we avoid duplicating it in all
385 * Rx paths. - Jean II */
386#ifdef CONFIG_WIRELESS_EXT
387#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
388 /* If spy monitoring on */
389 if (ieee->spy_data.spy_number > 0) {
390 struct iw_quality wstats;
391
392 wstats.updated = 0;
393 if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
394 wstats.level = rx_stats->signal;
395 wstats.updated |= IW_QUAL_LEVEL_UPDATED;
396 } else
397 wstats.updated |= IW_QUAL_LEVEL_INVALID;
398
399 if (rx_stats->mask & IEEE80211_STATMASK_NOISE) {
400 wstats.noise = rx_stats->noise;
401 wstats.updated |= IW_QUAL_NOISE_UPDATED;
402 } else
403 wstats.updated |= IW_QUAL_NOISE_INVALID;
404
405 if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) {
406 wstats.qual = rx_stats->signal;
407 wstats.updated |= IW_QUAL_QUAL_UPDATED;
408 } else
409 wstats.updated |= IW_QUAL_QUAL_INVALID;
410
411 /* Update spy records */
412 wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
413 }
414#endif /* IW_WIRELESS_SPY */
415#endif /* CONFIG_WIRELESS_EXT */
416
417#ifdef NOT_YET
418 hostap_update_rx_stats(local->ap, hdr, rx_stats);
419#endif
420
421 if (ieee->iw_mode == IW_MODE_MONITOR) {
422 stats->rx_packets++;
423 stats->rx_bytes += skb->len;
424 ieee80211_monitor_rx(ieee, skb, rx_stats);
425 return 1;
426 }
427
428 can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) ||
429 is_broadcast_ether_addr(hdr->addr2)) ?
430 ieee->host_mc_decrypt : ieee->host_decrypt;
431
432 if (can_be_decrypted) {
433 if (skb->len >= hdrlen + 3) {
434 /* Top two-bits of byte 3 are the key index */
435 keyidx = skb->data[hdrlen + 3] >> 6;
436 }
437
438 /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx
439 * is only allowed 2-bits of storage, no value of keyidx can
440 * be provided via above code that would result in keyidx
441 * being out of range */
442 crypt = ieee->crypt[keyidx];
443
444#ifdef NOT_YET
445 sta = NULL;
446
447 /* Use station specific key to override default keys if the
448 * receiver address is a unicast address ("individual RA"). If
449 * bcrx_sta_key parameter is set, station specific key is used
450 * even with broad/multicast targets (this is against IEEE
451 * 802.11, but makes it easier to use different keys with
452 * stations that do not support WEP key mapping). */
453
454 if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
455 (void)hostap_handle_sta_crypto(local, hdr, &crypt,
456 &sta);
457#endif
458
459 /* allow NULL decrypt to indicate an station specific override
460 * for default encryption */
461 if (crypt && (crypt->ops == NULL ||
462 crypt->ops->decrypt_mpdu == NULL))
463 crypt = NULL;
464
465 if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) {
466 /* This seems to be triggered by some (multicast?)
467 * frames from other than current BSS, so just drop the
468 * frames silently instead of filling system log with
469 * these reports. */
470 IEEE80211_DEBUG_DROP("Decryption failed (not set)"
471 " (SA=" MAC_FMT ")\n",
472 hdr->addr2[0], hdr->addr2[1],
473 hdr->addr2[2], hdr->addr2[3],
474 hdr->addr2[4], hdr->addr2[5]);
475 ieee->ieee_stats.rx_discards_undecryptable++;
476 goto rx_dropped;
477 }
478 }
479#ifdef NOT_YET
480 if (type != WLAN_FC_TYPE_DATA) {
481 if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH &&
482 fc & IEEE80211_FCTL_PROTECTED && ieee->host_decrypt &&
483 (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) {
484 printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
485 "from " MAC_FMT "\n", dev->name,
486 hdr->addr2[0], hdr->addr2[1],
487 hdr->addr2[2], hdr->addr2[3],
488 hdr->addr2[4], hdr->addr2[5]);
489 /* TODO: could inform hostapd about this so that it
490 * could send auth failure report */
491 goto rx_dropped;
492 }
493
494 if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
495 goto rx_dropped;
496 else
497 goto rx_exit;
498 }
499#endif
500 /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */
501 if (sc == ieee->prev_seq_ctl)
502 goto rx_dropped;
503 else
504 ieee->prev_seq_ctl = sc;
505
506 /* Data frame - extract src/dst addresses */
507 if (skb->len < IEEE80211_3ADDR_LEN)
508 goto rx_dropped;
509
510 switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
511 case IEEE80211_FCTL_FROMDS:
512 memcpy(dst, hdr->addr1, ETH_ALEN);
513 memcpy(src, hdr->addr3, ETH_ALEN);
514 break;
515 case IEEE80211_FCTL_TODS:
516 memcpy(dst, hdr->addr3, ETH_ALEN);
517 memcpy(src, hdr->addr2, ETH_ALEN);
518 break;
519 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
520 if (skb->len < IEEE80211_4ADDR_LEN)
521 goto rx_dropped;
522 memcpy(dst, hdr->addr3, ETH_ALEN);
523 memcpy(src, hdr->addr4, ETH_ALEN);
524 break;
525 case 0:
526 memcpy(dst, hdr->addr1, ETH_ALEN);
527 memcpy(src, hdr->addr2, ETH_ALEN);
528 break;
529 }
530
531#ifdef NOT_YET
532 if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
533 goto rx_dropped;
534 if (wds) {
535 skb->dev = dev = wds;
536 stats = hostap_get_stats(dev);
537 }
538
539 if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
540 (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
541 IEEE80211_FCTL_FROMDS && ieee->stadev
542 && !compare_ether_addr(hdr->addr2, ieee->assoc_ap_addr)) {
543 /* Frame from BSSID of the AP for which we are a client */
544 skb->dev = dev = ieee->stadev;
545 stats = hostap_get_stats(dev);
546 from_assoc_ap = 1;
547 }
548#endif
549
550 dev->last_rx = jiffies;
551
552#ifdef NOT_YET
553 if ((ieee->iw_mode == IW_MODE_MASTER ||
554 ieee->iw_mode == IW_MODE_REPEAT) && !from_assoc_ap) {
555 switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
556 wds != NULL)) {
557 case AP_RX_CONTINUE_NOT_AUTHORIZED:
558 frame_authorized = 0;
559 break;
560 case AP_RX_CONTINUE:
561 frame_authorized = 1;
562 break;
563 case AP_RX_DROP:
564 goto rx_dropped;
565 case AP_RX_EXIT:
566 goto rx_exit;
567 }
568 }
569#endif
570
571 /* Nullfunc frames may have PS-bit set, so they must be passed to
572 * hostap_handle_sta_rx() before being dropped here. */
573
574 stype &= ~IEEE80211_STYPE_QOS_DATA;
575
576 if (stype != IEEE80211_STYPE_DATA &&
577 stype != IEEE80211_STYPE_DATA_CFACK &&
578 stype != IEEE80211_STYPE_DATA_CFPOLL &&
579 stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
580 if (stype != IEEE80211_STYPE_NULLFUNC)
581 IEEE80211_DEBUG_DROP("RX: dropped data frame "
582 "with no data (type=0x%02x, "
583 "subtype=0x%02x, len=%d)\n",
584 type, stype, skb->len);
585 goto rx_dropped;
586 }
587
588 /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
589
590 if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
591 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
592 goto rx_dropped;
593
594 hdr = (struct ieee80211_hdr_4addr *)skb->data;
595
596 /* skb: hdr + (possibly fragmented) plaintext payload */
597 // PR: FIXME: hostap has additional conditions in the "if" below:
598 // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
599 if ((frag != 0) || (fc & IEEE80211_FCTL_MOREFRAGS)) {
600 int flen;
601 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
602 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
603
604 if (!frag_skb) {
605 IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
606 "Rx cannot get skb from fragment "
607 "cache (morefrag=%d seq=%u frag=%u)\n",
608 (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
609 WLAN_GET_SEQ_SEQ(sc), frag);
610 goto rx_dropped;
611 }
612
613 flen = skb->len;
614 if (frag != 0)
615 flen -= hdrlen;
616
617 if (frag_skb->tail + flen > frag_skb->end) {
618 printk(KERN_WARNING "%s: host decrypted and "
619 "reassembled frame did not fit skb\n",
620 dev->name);
621 ieee80211_frag_cache_invalidate(ieee, hdr);
622 goto rx_dropped;
623 }
624
625 if (frag == 0) {
626 /* copy first fragment (including full headers) into
627 * beginning of the fragment cache skb */
628 skb_copy_from_linear_data(skb, skb_put(frag_skb, flen), flen);
629 } else {
630 /* append frame payload to the end of the fragment
631 * cache skb */
632 skb_copy_from_linear_data_offset(skb, hdrlen,
633 skb_put(frag_skb, flen), flen);
634 }
635 dev_kfree_skb_any(skb);
636 skb = NULL;
637
638 if (fc & IEEE80211_FCTL_MOREFRAGS) {
639 /* more fragments expected - leave the skb in fragment
640 * cache for now; it will be delivered to upper layers
641 * after all fragments have been received */
642 goto rx_exit;
643 }
644
645 /* this was the last fragment and the frame will be
646 * delivered, so remove skb from fragment cache */
647 skb = frag_skb;
648 hdr = (struct ieee80211_hdr_4addr *)skb->data;
649 ieee80211_frag_cache_invalidate(ieee, hdr);
650 }
651
652 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
653 * encrypted/authenticated */
654 if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
655 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
656 goto rx_dropped;
657
658 hdr = (struct ieee80211_hdr_4addr *)skb->data;
659 if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
660 if ( /*ieee->ieee802_1x && */
661 ieee80211_is_eapol_frame(ieee, skb)) {
662 /* pass unencrypted EAPOL frames even if encryption is
663 * configured */
664 } else {
665 IEEE80211_DEBUG_DROP("encryption configured, but RX "
666 "frame not encrypted (SA="
667 MAC_FMT ")\n",
668 hdr->addr2[0], hdr->addr2[1],
669 hdr->addr2[2], hdr->addr2[3],
670 hdr->addr2[4], hdr->addr2[5]);
671 goto rx_dropped;
672 }
673 }
674
675 if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep &&
676 !ieee80211_is_eapol_frame(ieee, skb)) {
677 IEEE80211_DEBUG_DROP("dropped unencrypted RX data "
678 "frame from " MAC_FMT
679 " (drop_unencrypted=1)\n",
680 hdr->addr2[0], hdr->addr2[1],
681 hdr->addr2[2], hdr->addr2[3],
682 hdr->addr2[4], hdr->addr2[5]);
683 goto rx_dropped;
684 }
685
686 /* If the frame was decrypted in hardware, we may need to strip off
687 * any security data (IV, ICV, etc) that was left behind */
688 if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) &&
689 ieee->host_strip_iv_icv) {
690 int trimlen = 0;
691
692 /* Top two-bits of byte 3 are the key index */
693 if (skb->len >= hdrlen + 3)
694 keyidx = skb->data[hdrlen + 3] >> 6;
695
696 /* To strip off any security data which appears before the
697 * payload, we simply increase hdrlen (as the header gets
698 * chopped off immediately below). For the security data which
699 * appears after the payload, we use skb_trim. */
700
701 switch (ieee->sec.encode_alg[keyidx]) {
702 case SEC_ALG_WEP:
703 /* 4 byte IV */
704 hdrlen += 4;
705 /* 4 byte ICV */
706 trimlen = 4;
707 break;
708 case SEC_ALG_TKIP:
709 /* 4 byte IV, 4 byte ExtIV */
710 hdrlen += 8;
711 /* 8 byte MIC, 4 byte ICV */
712 trimlen = 12;
713 break;
714 case SEC_ALG_CCMP:
715 /* 8 byte CCMP header */
716 hdrlen += 8;
717 /* 8 byte MIC */
718 trimlen = 8;
719 break;
720 }
721
722 if (skb->len < trimlen)
723 goto rx_dropped;
724
725 __skb_trim(skb, skb->len - trimlen);
726
727 if (skb->len < hdrlen)
728 goto rx_dropped;
729 }
730
731 /* skb: hdr + (possible reassembled) full plaintext payload */
732
733 payload = skb->data + hdrlen;
734 ethertype = (payload[6] << 8) | payload[7];
735
736#ifdef NOT_YET
737 /* If IEEE 802.1X is used, check whether the port is authorized to send
738 * the received frame. */
739 if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) {
740 if (ethertype == ETH_P_PAE) {
741 printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n",
742 dev->name);
743 if (ieee->hostapd && ieee->apdev) {
744 /* Send IEEE 802.1X frames to the user
745 * space daemon for processing */
746 prism2_rx_80211(ieee->apdev, skb, rx_stats,
747 PRISM2_RX_MGMT);
748 ieee->apdevstats.rx_packets++;
749 ieee->apdevstats.rx_bytes += skb->len;
750 goto rx_exit;
751 }
752 } else if (!frame_authorized) {
753 printk(KERN_DEBUG "%s: dropped frame from "
754 "unauthorized port (IEEE 802.1X): "
755 "ethertype=0x%04x\n", dev->name, ethertype);
756 goto rx_dropped;
757 }
758 }
759#endif
760
761 /* convert hdr + possible LLC headers into Ethernet header */
762 if (skb->len - hdrlen >= 8 &&
763 ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
764 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
765 memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
766 /* remove RFC1042 or Bridge-Tunnel encapsulation and
767 * replace EtherType */
768 skb_pull(skb, hdrlen + SNAP_SIZE);
769 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
770 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
771 } else {
772 __be16 len;
773 /* Leave Ethernet header part of hdr and full payload */
774 skb_pull(skb, hdrlen);
775 len = htons(skb->len);
776 memcpy(skb_push(skb, 2), &len, 2);
777 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
778 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
779 }
780
781#ifdef NOT_YET
782 if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
783 IEEE80211_FCTL_TODS) && skb->len >= ETH_HLEN + ETH_ALEN) {
784 /* Non-standard frame: get addr4 from its bogus location after
785 * the payload */
786 skb_copy_to_linear_data_offset(skb, ETH_ALEN,
787 skb->data + skb->len - ETH_ALEN,
788 ETH_ALEN);
789 skb_trim(skb, skb->len - ETH_ALEN);
790 }
791#endif
792
793 stats->rx_packets++;
794 stats->rx_bytes += skb->len;
795
796#ifdef NOT_YET
797 if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) {
798 if (dst[0] & 0x01) {
799 /* copy multicast frame both to the higher layers and
800 * to the wireless media */
801 ieee->ap->bridged_multicast++;
802 skb2 = skb_clone(skb, GFP_ATOMIC);
803 if (skb2 == NULL)
804 printk(KERN_DEBUG "%s: skb_clone failed for "
805 "multicast frame\n", dev->name);
806 } else if (hostap_is_sta_assoc(ieee->ap, dst)) {
807 /* send frame directly to the associated STA using
808 * wireless media and not passing to higher layers */
809 ieee->ap->bridged_unicast++;
810 skb2 = skb;
811 skb = NULL;
812 }
813 }
814
815 if (skb2 != NULL) {
816 /* send to wireless media */
817 skb2->dev = dev;
818 skb2->protocol = htons(ETH_P_802_3);
819 skb_reset_mac_header(skb2);
820 skb_reset_network_header(skb2);
821 /* skb2->network_header += ETH_HLEN; */
822 dev_queue_xmit(skb2);
823 }
824#endif
825
826 if (skb) {
827 skb->protocol = eth_type_trans(skb, dev);
828 memset(skb->cb, 0, sizeof(skb->cb));
829 skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
830 if (netif_rx(skb) == NET_RX_DROP) {
831 /* netif_rx always succeeds, but it might drop
832 * the packet. If it drops the packet, we log that
833 * in our stats. */
834 IEEE80211_DEBUG_DROP
835 ("RX: netif_rx dropped the packet\n");
836 stats->rx_dropped++;
837 }
838 }
839
840 rx_exit:
841#ifdef NOT_YET
842 if (sta)
843 hostap_handle_sta_release(sta);
844#endif
845 return 1;
846
847 rx_dropped:
848 stats->rx_dropped++;
849
850 /* Returning 0 indicates to caller that we have not handled the SKB--
851 * so it is still allocated and can be used again by underlying
852 * hardware as a DMA target */
853 return 0;
854}
855
856/* Filter out unrelated packets, call ieee80211_rx[_mgt]
857 * This function takes over the skb, it should not be used again after calling
858 * this function. */
859void ieee80211_rx_any(struct ieee80211_device *ieee,
860 struct sk_buff *skb, struct ieee80211_rx_stats *stats)
861{
862 struct ieee80211_hdr_4addr *hdr;
863 int is_packet_for_us;
864 u16 fc;
865
866 if (ieee->iw_mode == IW_MODE_MONITOR) {
867 if (!ieee80211_rx(ieee, skb, stats))
868 dev_kfree_skb_irq(skb);
869 return;
870 }
871
872 if (skb->len < sizeof(struct ieee80211_hdr))
873 goto drop_free;
874
875 hdr = (struct ieee80211_hdr_4addr *)skb->data;
876 fc = le16_to_cpu(hdr->frame_ctl);
877
878 if ((fc & IEEE80211_FCTL_VERS) != 0)
879 goto drop_free;
880
881 switch (fc & IEEE80211_FCTL_FTYPE) {
882 case IEEE80211_FTYPE_MGMT:
883 if (skb->len < sizeof(struct ieee80211_hdr_3addr))
884 goto drop_free;
885 ieee80211_rx_mgt(ieee, hdr, stats);
886 dev_kfree_skb_irq(skb);
887 return;
888 case IEEE80211_FTYPE_DATA:
889 break;
890 case IEEE80211_FTYPE_CTL:
891 return;
892 default:
893 return;
894 }
895
896 is_packet_for_us = 0;
897 switch (ieee->iw_mode) {
898 case IW_MODE_ADHOC:
899 /* our BSS and not from/to DS */
900 if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
901 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
902 /* promisc: get all */
903 if (ieee->dev->flags & IFF_PROMISC)
904 is_packet_for_us = 1;
905 /* to us */
906 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
907 is_packet_for_us = 1;
908 /* mcast */
909 else if (is_multicast_ether_addr(hdr->addr1))
910 is_packet_for_us = 1;
911 }
912 break;
913 case IW_MODE_INFRA:
914 /* our BSS (== from our AP) and from DS */
915 if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
916 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
917 /* promisc: get all */
918 if (ieee->dev->flags & IFF_PROMISC)
919 is_packet_for_us = 1;
920 /* to us */
921 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
922 is_packet_for_us = 1;
923 /* mcast */
924 else if (is_multicast_ether_addr(hdr->addr1)) {
925 /* not our own packet bcasted from AP */
926 if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
927 is_packet_for_us = 1;
928 }
929 }
930 break;
931 default:
932 /* ? */
933 break;
934 }
935
936 if (is_packet_for_us)
937 if (!ieee80211_rx(ieee, skb, stats))
938 dev_kfree_skb_irq(skb);
939 return;
940
941drop_free:
942 dev_kfree_skb_irq(skb);
943 ieee->stats.rx_dropped++;
944 return;
945}
946
947#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
948
949static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
950
951/*
952* Make ther structure we read from the beacon packet has
953* the right values
954*/
955static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
956 *info_element, int sub_type)
957{
958
959 if (info_element->qui_subtype != sub_type)
960 return -1;
961 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
962 return -1;
963 if (info_element->qui_type != QOS_OUI_TYPE)
964 return -1;
965 if (info_element->version != QOS_VERSION_1)
966 return -1;
967
968 return 0;
969}
970
971/*
972 * Parse a QoS parameter element
973 */
974static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
975 *element_param, struct ieee80211_info_element
976 *info_element)
977{
978 int ret = 0;
979 u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
980
981 if ((info_element == NULL) || (element_param == NULL))
982 return -1;
983
984 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
985 memcpy(element_param->info_element.qui, info_element->data,
986 info_element->len);
987 element_param->info_element.elementID = info_element->id;
988 element_param->info_element.length = info_element->len;
989 } else
990 ret = -1;
991 if (ret == 0)
992 ret = ieee80211_verify_qos_info(&element_param->info_element,
993 QOS_OUI_PARAM_SUB_TYPE);
994 return ret;
995}
996
997/*
998 * Parse a QoS information element
999 */
1000static int ieee80211_read_qos_info_element(struct
1001 ieee80211_qos_information_element
1002 *element_info, struct ieee80211_info_element
1003 *info_element)
1004{
1005 int ret = 0;
1006 u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
1007
1008 if (element_info == NULL)
1009 return -1;
1010 if (info_element == NULL)
1011 return -1;
1012
1013 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
1014 memcpy(element_info->qui, info_element->data,
1015 info_element->len);
1016 element_info->elementID = info_element->id;
1017 element_info->length = info_element->len;
1018 } else
1019 ret = -1;
1020
1021 if (ret == 0)
1022 ret = ieee80211_verify_qos_info(element_info,
1023 QOS_OUI_INFO_SUB_TYPE);
1024 return ret;
1025}
1026
1027/*
1028 * Write QoS parameters from the ac parameters.
1029 */
1030static int ieee80211_qos_convert_ac_to_parameters(struct
1031 ieee80211_qos_parameter_info
1032 *param_elm, struct
1033 ieee80211_qos_parameters
1034 *qos_param)
1035{
1036 int rc = 0;
1037 int i;
1038 struct ieee80211_qos_ac_parameter *ac_params;
1039 u32 txop;
1040 u8 cw_min;
1041 u8 cw_max;
1042
1043 for (i = 0; i < QOS_QUEUE_NUM; i++) {
1044 ac_params = &(param_elm->ac_params_record[i]);
1045
1046 qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
1047 qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
1048
1049 cw_min = ac_params->ecw_min_max & 0x0F;
1050 qos_param->cw_min[i] = cpu_to_le16((1 << cw_min) - 1);
1051
1052 cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
1053 qos_param->cw_max[i] = cpu_to_le16((1 << cw_max) - 1);
1054
1055 qos_param->flag[i] =
1056 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
1057
1058 txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
1059 qos_param->tx_op_limit[i] = cpu_to_le16(txop);
1060 }
1061 return rc;
1062}
1063
1064/*
1065 * we have a generic data element which it may contain QoS information or
1066 * parameters element. check the information element length to decide
1067 * which type to read
1068 */
1069static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
1070 *info_element,
1071 struct ieee80211_network *network)
1072{
1073 int rc = 0;
1074 struct ieee80211_qos_parameters *qos_param = NULL;
1075 struct ieee80211_qos_information_element qos_info_element;
1076
1077 rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
1078
1079 if (rc == 0) {
1080 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
1081 network->flags |= NETWORK_HAS_QOS_INFORMATION;
1082 } else {
1083 struct ieee80211_qos_parameter_info param_element;
1084
1085 rc = ieee80211_read_qos_param_element(&param_element,
1086 info_element);
1087 if (rc == 0) {
1088 qos_param = &(network->qos_data.parameters);
1089 ieee80211_qos_convert_ac_to_parameters(&param_element,
1090 qos_param);
1091 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
1092 network->qos_data.param_count =
1093 param_element.info_element.ac_info & 0x0F;
1094 }
1095 }
1096
1097 if (rc == 0) {
1098 IEEE80211_DEBUG_QOS("QoS is supported\n");
1099 network->qos_data.supported = 1;
1100 }
1101 return rc;
1102}
1103
1104#ifdef CONFIG_IEEE80211_DEBUG
1105#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1106
1107static const char *get_info_element_string(u16 id)
1108{
1109 switch (id) {
1110 MFIE_STRING(SSID);
1111 MFIE_STRING(RATES);
1112 MFIE_STRING(FH_SET);
1113 MFIE_STRING(DS_SET);
1114 MFIE_STRING(CF_SET);
1115 MFIE_STRING(TIM);
1116 MFIE_STRING(IBSS_SET);
1117 MFIE_STRING(COUNTRY);
1118 MFIE_STRING(HOP_PARAMS);
1119 MFIE_STRING(HOP_TABLE);
1120 MFIE_STRING(REQUEST);
1121 MFIE_STRING(CHALLENGE);
1122 MFIE_STRING(POWER_CONSTRAINT);
1123 MFIE_STRING(POWER_CAPABILITY);
1124 MFIE_STRING(TPC_REQUEST);
1125 MFIE_STRING(TPC_REPORT);
1126 MFIE_STRING(SUPP_CHANNELS);
1127 MFIE_STRING(CSA);
1128 MFIE_STRING(MEASURE_REQUEST);
1129 MFIE_STRING(MEASURE_REPORT);
1130 MFIE_STRING(QUIET);
1131 MFIE_STRING(IBSS_DFS);
1132 MFIE_STRING(ERP_INFO);
1133 MFIE_STRING(RSN);
1134 MFIE_STRING(RATES_EX);
1135 MFIE_STRING(GENERIC);
1136 MFIE_STRING(QOS_PARAMETER);
1137 default:
1138 return "UNKNOWN";
1139 }
1140}
1141#endif
1142
1143static int ieee80211_parse_info_param(struct ieee80211_info_element
1144 *info_element, u16 length,
1145 struct ieee80211_network *network)
1146{
1147 u8 i;
1148#ifdef CONFIG_IEEE80211_DEBUG
1149 char rates_str[64];
1150 char *p;
1151#endif
1152
1153 while (length >= sizeof(*info_element)) {
1154 if (sizeof(*info_element) + info_element->len > length) {
1155 IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
1156 "info_element->len + 2 > left : "
1157 "info_element->len+2=%zd left=%d, id=%d.\n",
1158 info_element->len +
1159 sizeof(*info_element),
1160 length, info_element->id);
1161 /* We stop processing but don't return an error here
1162 * because some misbehaviour APs break this rule. ie.
1163 * Orinoco AP1000. */
1164 break;
1165 }
1166
1167 switch (info_element->id) {
1168 case MFIE_TYPE_SSID:
1169 if (ieee80211_is_empty_essid(info_element->data,
1170 info_element->len)) {
1171 network->flags |= NETWORK_EMPTY_ESSID;
1172 break;
1173 }
1174
1175 network->ssid_len = min(info_element->len,
1176 (u8) IW_ESSID_MAX_SIZE);
1177 memcpy(network->ssid, info_element->data,
1178 network->ssid_len);
1179 if (network->ssid_len < IW_ESSID_MAX_SIZE)
1180 memset(network->ssid + network->ssid_len, 0,
1181 IW_ESSID_MAX_SIZE - network->ssid_len);
1182
1183 IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
1184 network->ssid, network->ssid_len);
1185 break;
1186
1187 case MFIE_TYPE_RATES:
1188#ifdef CONFIG_IEEE80211_DEBUG
1189 p = rates_str;
1190#endif
1191 network->rates_len = min(info_element->len,
1192 MAX_RATES_LENGTH);
1193 for (i = 0; i < network->rates_len; i++) {
1194 network->rates[i] = info_element->data[i];
1195#ifdef CONFIG_IEEE80211_DEBUG
1196 p += snprintf(p, sizeof(rates_str) -
1197 (p - rates_str), "%02X ",
1198 network->rates[i]);
1199#endif
1200 if (ieee80211_is_ofdm_rate
1201 (info_element->data[i])) {
1202 network->flags |= NETWORK_HAS_OFDM;
1203 if (info_element->data[i] &
1204 IEEE80211_BASIC_RATE_MASK)
1205 network->flags &=
1206 ~NETWORK_HAS_CCK;
1207 }
1208 }
1209
1210 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
1211 rates_str, network->rates_len);
1212 break;
1213
1214 case MFIE_TYPE_RATES_EX:
1215#ifdef CONFIG_IEEE80211_DEBUG
1216 p = rates_str;
1217#endif
1218 network->rates_ex_len = min(info_element->len,
1219 MAX_RATES_EX_LENGTH);
1220 for (i = 0; i < network->rates_ex_len; i++) {
1221 network->rates_ex[i] = info_element->data[i];
1222#ifdef CONFIG_IEEE80211_DEBUG
1223 p += snprintf(p, sizeof(rates_str) -
1224 (p - rates_str), "%02X ",
1225 network->rates[i]);
1226#endif
1227 if (ieee80211_is_ofdm_rate
1228 (info_element->data[i])) {
1229 network->flags |= NETWORK_HAS_OFDM;
1230 if (info_element->data[i] &
1231 IEEE80211_BASIC_RATE_MASK)
1232 network->flags &=
1233 ~NETWORK_HAS_CCK;
1234 }
1235 }
1236
1237 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1238 rates_str, network->rates_ex_len);
1239 break;
1240
1241 case MFIE_TYPE_DS_SET:
1242 IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
1243 info_element->data[0]);
1244 network->channel = info_element->data[0];
1245 break;
1246
1247 case MFIE_TYPE_FH_SET:
1248 IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
1249 break;
1250
1251 case MFIE_TYPE_CF_SET:
1252 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
1253 break;
1254
1255 case MFIE_TYPE_TIM:
1256 network->tim.tim_count = info_element->data[0];
1257 network->tim.tim_period = info_element->data[1];
1258 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
1259 break;
1260
1261 case MFIE_TYPE_ERP_INFO:
1262 network->erp_value = info_element->data[0];
1263 network->flags |= NETWORK_HAS_ERP_VALUE;
1264 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1265 network->erp_value);
1266 break;
1267
1268 case MFIE_TYPE_IBSS_SET:
1269 network->atim_window = info_element->data[0];
1270 IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1271 network->atim_window);
1272 break;
1273
1274 case MFIE_TYPE_CHALLENGE:
1275 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
1276 break;
1277
1278 case MFIE_TYPE_GENERIC:
1279 IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
1280 info_element->len);
1281 if (!ieee80211_parse_qos_info_param_IE(info_element,
1282 network))
1283 break;
1284
1285 if (info_element->len >= 4 &&
1286 info_element->data[0] == 0x00 &&
1287 info_element->data[1] == 0x50 &&
1288 info_element->data[2] == 0xf2 &&
1289 info_element->data[3] == 0x01) {
1290 network->wpa_ie_len = min(info_element->len + 2,
1291 MAX_WPA_IE_LEN);
1292 memcpy(network->wpa_ie, info_element,
1293 network->wpa_ie_len);
1294 }
1295 break;
1296
1297 case MFIE_TYPE_RSN:
1298 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
1299 info_element->len);
1300 network->rsn_ie_len = min(info_element->len + 2,
1301 MAX_WPA_IE_LEN);
1302 memcpy(network->rsn_ie, info_element,
1303 network->rsn_ie_len);
1304 break;
1305
1306 case MFIE_TYPE_QOS_PARAMETER:
1307 printk(KERN_ERR
1308 "QoS Error need to parse QOS_PARAMETER IE\n");
1309 break;
1310 /* 802.11h */
1311 case MFIE_TYPE_POWER_CONSTRAINT:
1312 network->power_constraint = info_element->data[0];
1313 network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
1314 break;
1315
1316 case MFIE_TYPE_CSA:
1317 network->power_constraint = info_element->data[0];
1318 network->flags |= NETWORK_HAS_CSA;
1319 break;
1320
1321 case MFIE_TYPE_QUIET:
1322 network->quiet.count = info_element->data[0];
1323 network->quiet.period = info_element->data[1];
1324 network->quiet.duration = info_element->data[2];
1325 network->quiet.offset = info_element->data[3];
1326 network->flags |= NETWORK_HAS_QUIET;
1327 break;
1328
1329 case MFIE_TYPE_IBSS_DFS:
1330 if (network->ibss_dfs)
1331 break;
1332 network->ibss_dfs = kmemdup(info_element->data,
1333 info_element->len,
1334 GFP_ATOMIC);
1335 if (!network->ibss_dfs)
1336 return 1;
1337 network->flags |= NETWORK_HAS_IBSS_DFS;
1338 break;
1339
1340 case MFIE_TYPE_TPC_REPORT:
1341 network->tpc_report.transmit_power =
1342 info_element->data[0];
1343 network->tpc_report.link_margin = info_element->data[1];
1344 network->flags |= NETWORK_HAS_TPC_REPORT;
1345 break;
1346
1347 default:
1348 IEEE80211_DEBUG_MGMT
1349 ("Unsupported info element: %s (%d)\n",
1350 get_info_element_string(info_element->id),
1351 info_element->id);
1352 break;
1353 }
1354
1355 length -= sizeof(*info_element) + info_element->len;
1356 info_element =
1357 (struct ieee80211_info_element *)&info_element->
1358 data[info_element->len];
1359 }
1360
1361 return 0;
1362}
1363
1364static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
1365 *frame, struct ieee80211_rx_stats *stats)
1366{
1367 struct ieee80211_network network_resp = {
1368 .ibss_dfs = NULL,
1369 };
1370 struct ieee80211_network *network = &network_resp;
1371 struct net_device *dev = ieee->dev;
1372
1373 network->flags = 0;
1374 network->qos_data.active = 0;
1375 network->qos_data.supported = 0;
1376 network->qos_data.param_count = 0;
1377 network->qos_data.old_param_count = 0;
1378
1379 //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
1380 network->atim_window = le16_to_cpu(frame->aid);
1381 network->listen_interval = le16_to_cpu(frame->status);
1382 memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
1383 network->capability = le16_to_cpu(frame->capability);
1384 network->last_scanned = jiffies;
1385 network->rates_len = network->rates_ex_len = 0;
1386 network->last_associate = 0;
1387 network->ssid_len = 0;
1388 network->erp_value =
1389 (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
1390
1391 if (stats->freq == IEEE80211_52GHZ_BAND) {
1392 /* for A band (No DS info) */
1393 network->channel = stats->received_channel;
1394 } else
1395 network->flags |= NETWORK_HAS_CCK;
1396
1397 network->wpa_ie_len = 0;
1398 network->rsn_ie_len = 0;
1399
1400 if (ieee80211_parse_info_param
1401 (frame->info_element, stats->len - sizeof(*frame), network))
1402 return 1;
1403
1404 network->mode = 0;
1405 if (stats->freq == IEEE80211_52GHZ_BAND)
1406 network->mode = IEEE_A;
1407 else {
1408 if (network->flags & NETWORK_HAS_OFDM)
1409 network->mode |= IEEE_G;
1410 if (network->flags & NETWORK_HAS_CCK)
1411 network->mode |= IEEE_B;
1412 }
1413
1414 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1415 network->flags |= NETWORK_EMPTY_ESSID;
1416
1417 memcpy(&network->stats, stats, sizeof(network->stats));
1418
1419 if (ieee->handle_assoc_response != NULL)
1420 ieee->handle_assoc_response(dev, frame, network);
1421
1422 return 0;
1423}
1424
1425/***************************************************/
1426
1427static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
1428 *beacon,
1429 struct ieee80211_network *network,
1430 struct ieee80211_rx_stats *stats)
1431{
1432 DECLARE_MAC_BUF(mac);
1433
1434 network->qos_data.active = 0;
1435 network->qos_data.supported = 0;
1436 network->qos_data.param_count = 0;
1437 network->qos_data.old_param_count = 0;
1438
1439 /* Pull out fixed field data */
1440 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
1441 network->capability = le16_to_cpu(beacon->capability);
1442 network->last_scanned = jiffies;
1443 network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
1444 network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
1445 network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
1446 /* Where to pull this? beacon->listen_interval; */
1447 network->listen_interval = 0x0A;
1448 network->rates_len = network->rates_ex_len = 0;
1449 network->last_associate = 0;
1450 network->ssid_len = 0;
1451 network->flags = 0;
1452 network->atim_window = 0;
1453 network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
1454 0x3 : 0x0;
1455
1456 if (stats->freq == IEEE80211_52GHZ_BAND) {
1457 /* for A band (No DS info) */
1458 network->channel = stats->received_channel;
1459 } else
1460 network->flags |= NETWORK_HAS_CCK;
1461
1462 network->wpa_ie_len = 0;
1463 network->rsn_ie_len = 0;
1464
1465 if (ieee80211_parse_info_param
1466 (beacon->info_element, stats->len - sizeof(*beacon), network))
1467 return 1;
1468
1469 network->mode = 0;
1470 if (stats->freq == IEEE80211_52GHZ_BAND)
1471 network->mode = IEEE_A;
1472 else {
1473 if (network->flags & NETWORK_HAS_OFDM)
1474 network->mode |= IEEE_G;
1475 if (network->flags & NETWORK_HAS_CCK)
1476 network->mode |= IEEE_B;
1477 }
1478
1479 if (network->mode == 0) {
1480 IEEE80211_DEBUG_SCAN("Filtered out '%s (%s)' "
1481 "network.\n",
1482 escape_essid(network->ssid,
1483 network->ssid_len),
1484 print_mac(mac, network->bssid));
1485 return 1;
1486 }
1487
1488 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1489 network->flags |= NETWORK_EMPTY_ESSID;
1490
1491 memcpy(&network->stats, stats, sizeof(network->stats));
1492
1493 return 0;
1494}
1495
1496static inline int is_same_network(struct ieee80211_network *src,
1497 struct ieee80211_network *dst)
1498{
1499 /* A network is only a duplicate if the channel, BSSID, and ESSID
1500 * all match. We treat all <hidden> with the same BSSID and channel
1501 * as one network */
1502 return ((src->ssid_len == dst->ssid_len) &&
1503 (src->channel == dst->channel) &&
1504 !compare_ether_addr(src->bssid, dst->bssid) &&
1505 !memcmp(src->ssid, dst->ssid, src->ssid_len));
1506}
1507
1508static void update_network(struct ieee80211_network *dst,
1509 struct ieee80211_network *src)
1510{
1511 int qos_active;
1512 u8 old_param;
1513 DECLARE_MAC_BUF(mac);
1514
1515 ieee80211_network_reset(dst);
1516 dst->ibss_dfs = src->ibss_dfs;
1517
1518 /* We only update the statistics if they were created by receiving
1519 * the network information on the actual channel the network is on.
1520 *
1521 * This keeps beacons received on neighbor channels from bringing
1522 * down the signal level of an AP. */
1523 if (dst->channel == src->stats.received_channel)
1524 memcpy(&dst->stats, &src->stats,
1525 sizeof(struct ieee80211_rx_stats));
1526 else
1527 IEEE80211_DEBUG_SCAN("Network %s info received "
1528 "off channel (%d vs. %d)\n", print_mac(mac, src->bssid),
1529 dst->channel, src->stats.received_channel);
1530
1531 dst->capability = src->capability;
1532 memcpy(dst->rates, src->rates, src->rates_len);
1533 dst->rates_len = src->rates_len;
1534 memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
1535 dst->rates_ex_len = src->rates_ex_len;
1536
1537 dst->mode = src->mode;
1538 dst->flags = src->flags;
1539 dst->time_stamp[0] = src->time_stamp[0];
1540 dst->time_stamp[1] = src->time_stamp[1];
1541
1542 dst->beacon_interval = src->beacon_interval;
1543 dst->listen_interval = src->listen_interval;
1544 dst->atim_window = src->atim_window;
1545 dst->erp_value = src->erp_value;
1546 dst->tim = src->tim;
1547
1548 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1549 dst->wpa_ie_len = src->wpa_ie_len;
1550 memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
1551 dst->rsn_ie_len = src->rsn_ie_len;
1552
1553 dst->last_scanned = jiffies;
1554 qos_active = src->qos_data.active;
1555 old_param = dst->qos_data.old_param_count;
1556 if (dst->flags & NETWORK_HAS_QOS_MASK)
1557 memcpy(&dst->qos_data, &src->qos_data,
1558 sizeof(struct ieee80211_qos_data));
1559 else {
1560 dst->qos_data.supported = src->qos_data.supported;
1561 dst->qos_data.param_count = src->qos_data.param_count;
1562 }
1563
1564 if (dst->qos_data.supported == 1) {
1565 if (dst->ssid_len)
1566 IEEE80211_DEBUG_QOS
1567 ("QoS the network %s is QoS supported\n",
1568 dst->ssid);
1569 else
1570 IEEE80211_DEBUG_QOS
1571 ("QoS the network is QoS supported\n");
1572 }
1573 dst->qos_data.active = qos_active;
1574 dst->qos_data.old_param_count = old_param;
1575
1576 /* dst->last_associate is not overwritten */
1577}
1578
1579static inline int is_beacon(__le16 fc)
1580{
1581 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
1582}
1583
1584static void ieee80211_process_probe_response(struct ieee80211_device
1585 *ieee, struct
1586 ieee80211_probe_response
1587 *beacon, struct ieee80211_rx_stats
1588 *stats)
1589{
1590 struct net_device *dev = ieee->dev;
1591 struct ieee80211_network network = {
1592 .ibss_dfs = NULL,
1593 };
1594 struct ieee80211_network *target;
1595 struct ieee80211_network *oldest = NULL;
1596#ifdef CONFIG_IEEE80211_DEBUG
1597 struct ieee80211_info_element *info_element = beacon->info_element;
1598#endif
1599 unsigned long flags;
1600 DECLARE_MAC_BUF(mac);
1601
1602 IEEE80211_DEBUG_SCAN("'%s' (%s"
1603 "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
1604 escape_essid(info_element->data, info_element->len),
1605 print_mac(mac, beacon->header.addr3),
1606 (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
1607 (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
1608 (beacon->capability & cpu_to_le16(1 << 0xd)) ? '1' : '0',
1609 (beacon->capability & cpu_to_le16(1 << 0xc)) ? '1' : '0',
1610 (beacon->capability & cpu_to_le16(1 << 0xb)) ? '1' : '0',
1611 (beacon->capability & cpu_to_le16(1 << 0xa)) ? '1' : '0',
1612 (beacon->capability & cpu_to_le16(1 << 0x9)) ? '1' : '0',
1613 (beacon->capability & cpu_to_le16(1 << 0x8)) ? '1' : '0',
1614 (beacon->capability & cpu_to_le16(1 << 0x7)) ? '1' : '0',
1615 (beacon->capability & cpu_to_le16(1 << 0x6)) ? '1' : '0',
1616 (beacon->capability & cpu_to_le16(1 << 0x5)) ? '1' : '0',
1617 (beacon->capability & cpu_to_le16(1 << 0x4)) ? '1' : '0',
1618 (beacon->capability & cpu_to_le16(1 << 0x3)) ? '1' : '0',
1619 (beacon->capability & cpu_to_le16(1 << 0x2)) ? '1' : '0',
1620 (beacon->capability & cpu_to_le16(1 << 0x1)) ? '1' : '0',
1621 (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
1622
1623 if (ieee80211_network_init(ieee, beacon, &network, stats)) {
1624 IEEE80211_DEBUG_SCAN("Dropped '%s' (%s) via %s.\n",
1625 escape_essid(info_element->data,
1626 info_element->len),
1627 print_mac(mac, beacon->header.addr3),
1628 is_beacon(beacon->header.frame_ctl) ?
1629 "BEACON" : "PROBE RESPONSE");
1630 return;
1631 }
1632
1633 /* The network parsed correctly -- so now we scan our known networks
1634 * to see if we can find it in our list.
1635 *
1636 * NOTE: This search is definitely not optimized. Once its doing
1637 * the "right thing" we'll optimize it for efficiency if
1638 * necessary */
1639
1640 /* Search for this entry in the list and update it if it is
1641 * already there. */
1642
1643 spin_lock_irqsave(&ieee->lock, flags);
1644
1645 list_for_each_entry(target, &ieee->network_list, list) {
1646 if (is_same_network(target, &network))
1647 break;
1648
1649 if ((oldest == NULL) ||
1650 (target->last_scanned < oldest->last_scanned))
1651 oldest = target;
1652 }
1653
1654 /* If we didn't find a match, then get a new network slot to initialize
1655 * with this beacon's information */
1656 if (&target->list == &ieee->network_list) {
1657 if (list_empty(&ieee->network_free_list)) {
1658 /* If there are no more slots, expire the oldest */
1659 list_del(&oldest->list);
1660 target = oldest;
1661 IEEE80211_DEBUG_SCAN("Expired '%s' (%s) from "
1662 "network list.\n",
1663 escape_essid(target->ssid,
1664 target->ssid_len),
1665 print_mac(mac, target->bssid));
1666 ieee80211_network_reset(target);
1667 } else {
1668 /* Otherwise just pull from the free list */
1669 target = list_entry(ieee->network_free_list.next,
1670 struct ieee80211_network, list);
1671 list_del(ieee->network_free_list.next);
1672 }
1673
1674#ifdef CONFIG_IEEE80211_DEBUG
1675 IEEE80211_DEBUG_SCAN("Adding '%s' (%s) via %s.\n",
1676 escape_essid(network.ssid,
1677 network.ssid_len),
1678 print_mac(mac, network.bssid),
1679 is_beacon(beacon->header.frame_ctl) ?
1680 "BEACON" : "PROBE RESPONSE");
1681#endif
1682 memcpy(target, &network, sizeof(*target));
1683 network.ibss_dfs = NULL;
1684 list_add_tail(&target->list, &ieee->network_list);
1685 } else {
1686 IEEE80211_DEBUG_SCAN("Updating '%s' (%s) via %s.\n",
1687 escape_essid(target->ssid,
1688 target->ssid_len),
1689 print_mac(mac, target->bssid),
1690 is_beacon(beacon->header.frame_ctl) ?
1691 "BEACON" : "PROBE RESPONSE");
1692 update_network(target, &network);
1693 network.ibss_dfs = NULL;
1694 }
1695
1696 spin_unlock_irqrestore(&ieee->lock, flags);
1697
1698 if (is_beacon(beacon->header.frame_ctl)) {
1699 if (ieee->handle_beacon != NULL)
1700 ieee->handle_beacon(dev, beacon, target);
1701 } else {
1702 if (ieee->handle_probe_response != NULL)
1703 ieee->handle_probe_response(dev, beacon, target);
1704 }
1705}
1706
1707void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1708 struct ieee80211_hdr_4addr *header,
1709 struct ieee80211_rx_stats *stats)
1710{
1711 switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
1712 case IEEE80211_STYPE_ASSOC_RESP:
1713 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
1714 WLAN_FC_GET_STYPE(le16_to_cpu
1715 (header->frame_ctl)));
1716 ieee80211_handle_assoc_resp(ieee,
1717 (struct ieee80211_assoc_response *)
1718 header, stats);
1719 break;
1720
1721 case IEEE80211_STYPE_REASSOC_RESP:
1722 IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
1723 WLAN_FC_GET_STYPE(le16_to_cpu
1724 (header->frame_ctl)));
1725 break;
1726
1727 case IEEE80211_STYPE_PROBE_REQ:
1728 IEEE80211_DEBUG_MGMT("received auth (%d)\n",
1729 WLAN_FC_GET_STYPE(le16_to_cpu
1730 (header->frame_ctl)));
1731
1732 if (ieee->handle_probe_request != NULL)
1733 ieee->handle_probe_request(ieee->dev,
1734 (struct
1735 ieee80211_probe_request *)
1736 header, stats);
1737 break;
1738
1739 case IEEE80211_STYPE_PROBE_RESP:
1740 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1741 WLAN_FC_GET_STYPE(le16_to_cpu
1742 (header->frame_ctl)));
1743 IEEE80211_DEBUG_SCAN("Probe response\n");
1744 ieee80211_process_probe_response(ieee,
1745 (struct
1746 ieee80211_probe_response *)
1747 header, stats);
1748 break;
1749
1750 case IEEE80211_STYPE_BEACON:
1751 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1752 WLAN_FC_GET_STYPE(le16_to_cpu
1753 (header->frame_ctl)));
1754 IEEE80211_DEBUG_SCAN("Beacon\n");
1755 ieee80211_process_probe_response(ieee,
1756 (struct
1757 ieee80211_probe_response *)
1758 header, stats);
1759 break;
1760 case IEEE80211_STYPE_AUTH:
1761
1762 IEEE80211_DEBUG_MGMT("received auth (%d)\n",
1763 WLAN_FC_GET_STYPE(le16_to_cpu
1764 (header->frame_ctl)));
1765
1766 if (ieee->handle_auth != NULL)
1767 ieee->handle_auth(ieee->dev,
1768 (struct ieee80211_auth *)header);
1769 break;
1770
1771 case IEEE80211_STYPE_DISASSOC:
1772 if (ieee->handle_disassoc != NULL)
1773 ieee->handle_disassoc(ieee->dev,
1774 (struct ieee80211_disassoc *)
1775 header);
1776 break;
1777
1778 case IEEE80211_STYPE_ACTION:
1779 IEEE80211_DEBUG_MGMT("ACTION\n");
1780 if (ieee->handle_action)
1781 ieee->handle_action(ieee->dev,
1782 (struct ieee80211_action *)
1783 header, stats);
1784 break;
1785
1786 case IEEE80211_STYPE_REASSOC_REQ:
1787 IEEE80211_DEBUG_MGMT("received reassoc (%d)\n",
1788 WLAN_FC_GET_STYPE(le16_to_cpu
1789 (header->frame_ctl)));
1790
1791 IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n",
1792 ieee->dev->name);
1793 if (ieee->handle_reassoc_request != NULL)
1794 ieee->handle_reassoc_request(ieee->dev,
1795 (struct ieee80211_reassoc_request *)
1796 header);
1797 break;
1798
1799 case IEEE80211_STYPE_ASSOC_REQ:
1800 IEEE80211_DEBUG_MGMT("received assoc (%d)\n",
1801 WLAN_FC_GET_STYPE(le16_to_cpu
1802 (header->frame_ctl)));
1803
1804 IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n",
1805 ieee->dev->name);
1806 if (ieee->handle_assoc_request != NULL)
1807 ieee->handle_assoc_request(ieee->dev);
1808 break;
1809
1810 case IEEE80211_STYPE_DEAUTH:
1811 IEEE80211_DEBUG_MGMT("DEAUTH\n");
1812 if (ieee->handle_deauth != NULL)
1813 ieee->handle_deauth(ieee->dev,
1814 (struct ieee80211_deauth *)
1815 header);
1816 break;
1817 default:
1818 IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
1819 WLAN_FC_GET_STYPE(le16_to_cpu
1820 (header->frame_ctl)));
1821 IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n",
1822 ieee->dev->name,
1823 WLAN_FC_GET_STYPE(le16_to_cpu
1824 (header->frame_ctl)));
1825 break;
1826 }
1827}
1828
1829EXPORT_SYMBOL_GPL(ieee80211_rx_any);
1830EXPORT_SYMBOL(ieee80211_rx_mgt);
1831EXPORT_SYMBOL(ieee80211_rx);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
deleted file mode 100644
index d996547f7a62..000000000000
--- a/net/ieee80211/ieee80211_tx.c
+++ /dev/null
@@ -1,545 +0,0 @@
1/******************************************************************************
2
3 Copyright(c) 2003 - 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/errno.h>
28#include <linux/if_arp.h>
29#include <linux/in6.h>
30#include <linux/in.h>
31#include <linux/ip.h>
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/netdevice.h>
35#include <linux/proc_fs.h>
36#include <linux/skbuff.h>
37#include <linux/slab.h>
38#include <linux/tcp.h>
39#include <linux/types.h>
40#include <linux/wireless.h>
41#include <linux/etherdevice.h>
42#include <asm/uaccess.h>
43
44#include <net/ieee80211.h>
45
46/*
47
48802.11 Data Frame
49
50 ,-------------------------------------------------------------------.
51Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
52 |------|------|---------|---------|---------|------|---------|------|
53Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
54 | | tion | (BSSID) | | | ence | data | |
55 `--------------------------------------------------| |------'
56Total: 28 non-data bytes `----.----'
57 |
58 .- 'Frame data' expands, if WEP enabled, to <----------'
59 |
60 V
61 ,-----------------------.
62Bytes | 4 | 0-2296 | 4 |
63 |-----|-----------|-----|
64Desc. | IV | Encrypted | ICV |
65 | | Packet | |
66 `-----| |-----'
67 `-----.-----'
68 |
69 .- 'Encrypted Packet' expands to
70 |
71 V
72 ,---------------------------------------------------.
73Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
74 |------|------|---------|----------|------|---------|
75Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
76 | DSAP | SSAP | | | | Packet |
77 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
78 `----------------------------------------------------
79Total: 8 non-data bytes
80
81802.3 Ethernet Data Frame
82
83 ,-----------------------------------------.
84Bytes | 6 | 6 | 2 | Variable | 4 |
85 |-------|-------|------|-----------|------|
86Desc. | Dest. | Source| Type | IP Packet | fcs |
87 | MAC | MAC | | | |
88 `-----------------------------------------'
89Total: 18 non-data bytes
90
91In the event that fragmentation is required, the incoming payload is split into
92N parts of size ieee->fts. The first fragment contains the SNAP header and the
93remaining packets are just data.
94
95If encryption is enabled, each fragment payload size is reduced by enough space
96to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
97So if you have 1500 bytes of payload with ieee->fts set to 500 without
98encryption it will take 3 frames. With WEP it will take 4 frames as the
99payload of each frame is reduced to 492 bytes.
100
101* SKB visualization
102*
103* ,- skb->data
104* |
105* | ETHERNET HEADER ,-<-- PAYLOAD
106* | | 14 bytes from skb->data
107* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
108* | | | |
109* |,-Dest.--. ,--Src.---. | | |
110* | 6 bytes| | 6 bytes | | | |
111* v | | | | | |
112* 0 | v 1 | v | v 2
113* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
114* ^ | ^ | ^ |
115* | | | | | |
116* | | | | `T' <---- 2 bytes for Type
117* | | | |
118* | | '---SNAP--' <-------- 6 bytes for SNAP
119* | |
120* `-IV--' <-------------------- 4 bytes for IV (WEP)
121*
122* SNAP HEADER
123*
124*/
125
126static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
127static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
128
129static int ieee80211_copy_snap(u8 * data, __be16 h_proto)
130{
131 struct ieee80211_snap_hdr *snap;
132 u8 *oui;
133
134 snap = (struct ieee80211_snap_hdr *)data;
135 snap->dsap = 0xaa;
136 snap->ssap = 0xaa;
137 snap->ctrl = 0x03;
138
139 if (h_proto == htons(ETH_P_AARP) || h_proto == htons(ETH_P_IPX))
140 oui = P802_1H_OUI;
141 else
142 oui = RFC1042_OUI;
143 snap->oui[0] = oui[0];
144 snap->oui[1] = oui[1];
145 snap->oui[2] = oui[2];
146
147 memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16));
148
149 return SNAP_SIZE + sizeof(u16);
150}
151
152static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
153 struct sk_buff *frag, int hdr_len)
154{
155 struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
156 int res;
157
158 if (crypt == NULL)
159 return -1;
160
161 /* To encrypt, frame format is:
162 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
163 atomic_inc(&crypt->refcnt);
164 res = 0;
165 if (crypt->ops && crypt->ops->encrypt_mpdu)
166 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
167
168 atomic_dec(&crypt->refcnt);
169 if (res < 0) {
170 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
171 ieee->dev->name, frag->len);
172 ieee->ieee_stats.tx_discards++;
173 return -1;
174 }
175
176 return 0;
177}
178
179void ieee80211_txb_free(struct ieee80211_txb *txb)
180{
181 int i;
182 if (unlikely(!txb))
183 return;
184 for (i = 0; i < txb->nr_frags; i++)
185 if (txb->fragments[i])
186 dev_kfree_skb_any(txb->fragments[i]);
187 kfree(txb);
188}
189
190static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
191 int headroom, gfp_t gfp_mask)
192{
193 struct ieee80211_txb *txb;
194 int i;
195 txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
196 gfp_mask);
197 if (!txb)
198 return NULL;
199
200 memset(txb, 0, sizeof(struct ieee80211_txb));
201 txb->nr_frags = nr_frags;
202 txb->frag_size = txb_size;
203
204 for (i = 0; i < nr_frags; i++) {
205 txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,
206 gfp_mask);
207 if (unlikely(!txb->fragments[i])) {
208 i--;
209 break;
210 }
211 skb_reserve(txb->fragments[i], headroom);
212 }
213 if (unlikely(i != nr_frags)) {
214 while (i >= 0)
215 dev_kfree_skb_any(txb->fragments[i--]);
216 kfree(txb);
217 return NULL;
218 }
219 return txb;
220}
221
222static int ieee80211_classify(struct sk_buff *skb)
223{
224 struct ethhdr *eth;
225 struct iphdr *ip;
226
227 eth = (struct ethhdr *)skb->data;
228 if (eth->h_proto != htons(ETH_P_IP))
229 return 0;
230
231 ip = ip_hdr(skb);
232 switch (ip->tos & 0xfc) {
233 case 0x20:
234 return 2;
235 case 0x40:
236 return 1;
237 case 0x60:
238 return 3;
239 case 0x80:
240 return 4;
241 case 0xa0:
242 return 5;
243 case 0xc0:
244 return 6;
245 case 0xe0:
246 return 7;
247 default:
248 return 0;
249 }
250}
251
252/* Incoming skb is converted to a txb which consists of
253 * a block of 802.11 fragment packets (stored as skbs) */
254int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
255{
256 struct ieee80211_device *ieee = netdev_priv(dev);
257 struct ieee80211_txb *txb = NULL;
258 struct ieee80211_hdr_3addrqos *frag_hdr;
259 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
260 rts_required;
261 unsigned long flags;
262 struct net_device_stats *stats = &ieee->stats;
263 int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
264 __be16 ether_type;
265 int bytes, fc, hdr_len;
266 struct sk_buff *skb_frag;
267 struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */
268 .duration_id = 0,
269 .seq_ctl = 0,
270 .qos_ctl = 0
271 };
272 u8 dest[ETH_ALEN], src[ETH_ALEN];
273 struct ieee80211_crypt_data *crypt;
274 int priority = skb->priority;
275 int snapped = 0;
276
277 if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
278 return NETDEV_TX_BUSY;
279
280 spin_lock_irqsave(&ieee->lock, flags);
281
282 /* If there is no driver handler to take the TXB, dont' bother
283 * creating it... */
284 if (!ieee->hard_start_xmit) {
285 printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
286 goto success;
287 }
288
289 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
290 printk(KERN_WARNING "%s: skb too small (%d).\n",
291 ieee->dev->name, skb->len);
292 goto success;
293 }
294
295 ether_type = ((struct ethhdr *)skb->data)->h_proto;
296
297 crypt = ieee->crypt[ieee->tx_keyidx];
298
299 encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) &&
300 ieee->sec.encrypt;
301
302 host_encrypt = ieee->host_encrypt && encrypt && crypt;
303 host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
304 host_build_iv = ieee->host_build_iv && encrypt && crypt;
305
306 if (!encrypt && ieee->ieee802_1x &&
307 ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) {
308 stats->tx_dropped++;
309 goto success;
310 }
311
312 /* Save source and destination addresses */
313 skb_copy_from_linear_data(skb, dest, ETH_ALEN);
314 skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN);
315
316 if (host_encrypt || host_build_iv)
317 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
318 IEEE80211_FCTL_PROTECTED;
319 else
320 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
321
322 if (ieee->iw_mode == IW_MODE_INFRA) {
323 fc |= IEEE80211_FCTL_TODS;
324 /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
325 memcpy(header.addr1, ieee->bssid, ETH_ALEN);
326 memcpy(header.addr2, src, ETH_ALEN);
327 memcpy(header.addr3, dest, ETH_ALEN);
328 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
329 /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
330 memcpy(header.addr1, dest, ETH_ALEN);
331 memcpy(header.addr2, src, ETH_ALEN);
332 memcpy(header.addr3, ieee->bssid, ETH_ALEN);
333 }
334 hdr_len = IEEE80211_3ADDR_LEN;
335
336 if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
337 fc |= IEEE80211_STYPE_QOS_DATA;
338 hdr_len += 2;
339
340 skb->priority = ieee80211_classify(skb);
341 header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID);
342 }
343 header.frame_ctl = cpu_to_le16(fc);
344
345 /* Advance the SKB to the start of the payload */
346 skb_pull(skb, sizeof(struct ethhdr));
347
348 /* Determine total amount of storage required for TXB packets */
349 bytes = skb->len + SNAP_SIZE + sizeof(u16);
350
351 /* Encrypt msdu first on the whole data packet. */
352 if ((host_encrypt || host_encrypt_msdu) &&
353 crypt && crypt->ops && crypt->ops->encrypt_msdu) {
354 int res = 0;
355 int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
356 crypt->ops->extra_msdu_postfix_len;
357 struct sk_buff *skb_new = dev_alloc_skb(len);
358
359 if (unlikely(!skb_new))
360 goto failed;
361
362 skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
363 memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
364 snapped = 1;
365 ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
366 ether_type);
367 skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len);
368 res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
369 if (res < 0) {
370 IEEE80211_ERROR("msdu encryption failed\n");
371 dev_kfree_skb_any(skb_new);
372 goto failed;
373 }
374 dev_kfree_skb_any(skb);
375 skb = skb_new;
376 bytes += crypt->ops->extra_msdu_prefix_len +
377 crypt->ops->extra_msdu_postfix_len;
378 skb_pull(skb, hdr_len);
379 }
380
381 if (host_encrypt || ieee->host_open_frag) {
382 /* Determine fragmentation size based on destination (multicast
383 * and broadcast are not fragmented) */
384 if (is_multicast_ether_addr(dest) ||
385 is_broadcast_ether_addr(dest))
386 frag_size = MAX_FRAG_THRESHOLD;
387 else
388 frag_size = ieee->fts;
389
390 /* Determine amount of payload per fragment. Regardless of if
391 * this stack is providing the full 802.11 header, one will
392 * eventually be affixed to this fragment -- so we must account
393 * for it when determining the amount of payload space. */
394 bytes_per_frag = frag_size - hdr_len;
395 if (ieee->config &
396 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
397 bytes_per_frag -= IEEE80211_FCS_LEN;
398
399 /* Each fragment may need to have room for encryptiong
400 * pre/postfix */
401 if (host_encrypt)
402 bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
403 crypt->ops->extra_mpdu_postfix_len;
404
405 /* Number of fragments is the total
406 * bytes_per_frag / payload_per_fragment */
407 nr_frags = bytes / bytes_per_frag;
408 bytes_last_frag = bytes % bytes_per_frag;
409 if (bytes_last_frag)
410 nr_frags++;
411 else
412 bytes_last_frag = bytes_per_frag;
413 } else {
414 nr_frags = 1;
415 bytes_per_frag = bytes_last_frag = bytes;
416 frag_size = bytes + hdr_len;
417 }
418
419 rts_required = (frag_size > ieee->rts
420 && ieee->config & CFG_IEEE80211_RTS);
421 if (rts_required)
422 nr_frags++;
423
424 /* When we allocate the TXB we allocate enough space for the reserve
425 * and full fragment bytes (bytes_per_frag doesn't include prefix,
426 * postfix, header, FCS, etc.) */
427 txb = ieee80211_alloc_txb(nr_frags, frag_size,
428 ieee->tx_headroom, GFP_ATOMIC);
429 if (unlikely(!txb)) {
430 printk(KERN_WARNING "%s: Could not allocate TXB\n",
431 ieee->dev->name);
432 goto failed;
433 }
434 txb->encrypted = encrypt;
435 if (host_encrypt)
436 txb->payload_size = frag_size * (nr_frags - 1) +
437 bytes_last_frag;
438 else
439 txb->payload_size = bytes;
440
441 if (rts_required) {
442 skb_frag = txb->fragments[0];
443 frag_hdr =
444 (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
445
446 /*
447 * Set header frame_ctl to the RTS.
448 */
449 header.frame_ctl =
450 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
451 memcpy(frag_hdr, &header, hdr_len);
452
453 /*
454 * Restore header frame_ctl to the original data setting.
455 */
456 header.frame_ctl = cpu_to_le16(fc);
457
458 if (ieee->config &
459 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
460 skb_put(skb_frag, 4);
461
462 txb->rts_included = 1;
463 i = 1;
464 } else
465 i = 0;
466
467 for (; i < nr_frags; i++) {
468 skb_frag = txb->fragments[i];
469
470 if (host_encrypt || host_build_iv)
471 skb_reserve(skb_frag,
472 crypt->ops->extra_mpdu_prefix_len);
473
474 frag_hdr =
475 (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
476 memcpy(frag_hdr, &header, hdr_len);
477
478 /* If this is not the last fragment, then add the MOREFRAGS
479 * bit to the frame control */
480 if (i != nr_frags - 1) {
481 frag_hdr->frame_ctl =
482 cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
483 bytes = bytes_per_frag;
484 } else {
485 /* The last fragment takes the remaining length */
486 bytes = bytes_last_frag;
487 }
488
489 if (i == 0 && !snapped) {
490 ieee80211_copy_snap(skb_put
491 (skb_frag, SNAP_SIZE + sizeof(u16)),
492 ether_type);
493 bytes -= SNAP_SIZE + sizeof(u16);
494 }
495
496 skb_copy_from_linear_data(skb, skb_put(skb_frag, bytes), bytes);
497
498 /* Advance the SKB... */
499 skb_pull(skb, bytes);
500
501 /* Encryption routine will move the header forward in order
502 * to insert the IV between the header and the payload */
503 if (host_encrypt)
504 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
505 else if (host_build_iv) {
506 atomic_inc(&crypt->refcnt);
507 if (crypt->ops->build_iv)
508 crypt->ops->build_iv(skb_frag, hdr_len,
509 ieee->sec.keys[ieee->sec.active_key],
510 ieee->sec.key_sizes[ieee->sec.active_key],
511 crypt->priv);
512 atomic_dec(&crypt->refcnt);
513 }
514
515 if (ieee->config &
516 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
517 skb_put(skb_frag, 4);
518 }
519
520 success:
521 spin_unlock_irqrestore(&ieee->lock, flags);
522
523 dev_kfree_skb_any(skb);
524
525 if (txb) {
526 int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
527 if (ret == 0) {
528 stats->tx_packets++;
529 stats->tx_bytes += txb->payload_size;
530 return 0;
531 }
532
533 ieee80211_txb_free(txb);
534 }
535
536 return 0;
537
538 failed:
539 spin_unlock_irqrestore(&ieee->lock, flags);
540 netif_stop_queue(dev);
541 stats->tx_errors++;
542 return 1;
543}
544
545EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
deleted file mode 100644
index 973832dd7faf..000000000000
--- a/net/ieee80211/ieee80211_wx.c
+++ /dev/null
@@ -1,760 +0,0 @@
1/******************************************************************************
2
3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <j@w1.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31******************************************************************************/
32
33#include <linux/kmod.h>
34#include <linux/module.h>
35#include <linux/jiffies.h>
36
37#include <net/ieee80211.h>
38#include <linux/wireless.h>
39
40static const char *ieee80211_modes[] = {
41 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
42};
43
44#define MAX_CUSTOM_LEN 64
45static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
46 char *start, char *stop,
47 struct ieee80211_network *network,
48 struct iw_request_info *info)
49{
50 char custom[MAX_CUSTOM_LEN];
51 char *p;
52 struct iw_event iwe;
53 int i, j;
54 char *current_val; /* For rates */
55 u8 rate;
56
57 /* First entry *MUST* be the AP MAC address */
58 iwe.cmd = SIOCGIWAP;
59 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
60 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
61 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
62
63 /* Remaining entries will be displayed in the order we provide them */
64
65 /* Add the ESSID */
66 iwe.cmd = SIOCGIWESSID;
67 iwe.u.data.flags = 1;
68 if (network->flags & NETWORK_EMPTY_ESSID) {
69 iwe.u.data.length = sizeof("<hidden>");
70 start = iwe_stream_add_point(info, start, stop,
71 &iwe, "<hidden>");
72 } else {
73 iwe.u.data.length = min(network->ssid_len, (u8) 32);
74 start = iwe_stream_add_point(info, start, stop,
75 &iwe, network->ssid);
76 }
77
78 /* Add the protocol name */
79 iwe.cmd = SIOCGIWNAME;
80 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
81 ieee80211_modes[network->mode]);
82 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
83
84 /* Add mode */
85 iwe.cmd = SIOCGIWMODE;
86 if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
87 if (network->capability & WLAN_CAPABILITY_ESS)
88 iwe.u.mode = IW_MODE_MASTER;
89 else
90 iwe.u.mode = IW_MODE_ADHOC;
91
92 start = iwe_stream_add_event(info, start, stop,
93 &iwe, IW_EV_UINT_LEN);
94 }
95
96 /* Add channel and frequency */
97 /* Note : userspace automatically computes channel using iwrange */
98 iwe.cmd = SIOCGIWFREQ;
99 iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
100 iwe.u.freq.e = 6;
101 iwe.u.freq.i = 0;
102 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
103
104 /* Add encryption capability */
105 iwe.cmd = SIOCGIWENCODE;
106 if (network->capability & WLAN_CAPABILITY_PRIVACY)
107 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
108 else
109 iwe.u.data.flags = IW_ENCODE_DISABLED;
110 iwe.u.data.length = 0;
111 start = iwe_stream_add_point(info, start, stop,
112 &iwe, network->ssid);
113
114 /* Add basic and extended rates */
115 /* Rate : stuffing multiple values in a single event require a bit
116 * more of magic - Jean II */
117 current_val = start + iwe_stream_lcp_len(info);
118 iwe.cmd = SIOCGIWRATE;
119 /* Those two flags are ignored... */
120 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
121
122 for (i = 0, j = 0; i < network->rates_len;) {
123 if (j < network->rates_ex_len &&
124 ((network->rates_ex[j] & 0x7F) <
125 (network->rates[i] & 0x7F)))
126 rate = network->rates_ex[j++] & 0x7F;
127 else
128 rate = network->rates[i++] & 0x7F;
129 /* Bit rate given in 500 kb/s units (+ 0x80) */
130 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
131 /* Add new value to event */
132 current_val = iwe_stream_add_value(info, start, current_val,
133 stop, &iwe, IW_EV_PARAM_LEN);
134 }
135 for (; j < network->rates_ex_len; j++) {
136 rate = network->rates_ex[j] & 0x7F;
137 /* Bit rate given in 500 kb/s units (+ 0x80) */
138 iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
139 /* Add new value to event */
140 current_val = iwe_stream_add_value(info, start, current_val,
141 stop, &iwe, IW_EV_PARAM_LEN);
142 }
143 /* Check if we added any rate */
144 if ((current_val - start) > iwe_stream_lcp_len(info))
145 start = current_val;
146
147 /* Add quality statistics */
148 iwe.cmd = IWEVQUAL;
149 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
150 IW_QUAL_NOISE_UPDATED;
151
152 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
153 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
154 IW_QUAL_LEVEL_INVALID;
155 iwe.u.qual.qual = 0;
156 } else {
157 if (ieee->perfect_rssi == ieee->worst_rssi)
158 iwe.u.qual.qual = 100;
159 else
160 iwe.u.qual.qual =
161 (100 *
162 (ieee->perfect_rssi - ieee->worst_rssi) *
163 (ieee->perfect_rssi - ieee->worst_rssi) -
164 (ieee->perfect_rssi - network->stats.rssi) *
165 (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
166 62 * (ieee->perfect_rssi -
167 network->stats.rssi))) /
168 ((ieee->perfect_rssi -
169 ieee->worst_rssi) * (ieee->perfect_rssi -
170 ieee->worst_rssi));
171 if (iwe.u.qual.qual > 100)
172 iwe.u.qual.qual = 100;
173 else if (iwe.u.qual.qual < 1)
174 iwe.u.qual.qual = 0;
175 }
176
177 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
178 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
179 iwe.u.qual.noise = 0;
180 } else {
181 iwe.u.qual.noise = network->stats.noise;
182 }
183
184 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
185 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
186 iwe.u.qual.level = 0;
187 } else {
188 iwe.u.qual.level = network->stats.signal;
189 }
190
191 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
192
193 iwe.cmd = IWEVCUSTOM;
194 p = custom;
195
196 iwe.u.data.length = p - custom;
197 if (iwe.u.data.length)
198 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
199
200 memset(&iwe, 0, sizeof(iwe));
201 if (network->wpa_ie_len) {
202 char buf[MAX_WPA_IE_LEN];
203 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
204 iwe.cmd = IWEVGENIE;
205 iwe.u.data.length = network->wpa_ie_len;
206 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
207 }
208
209 memset(&iwe, 0, sizeof(iwe));
210 if (network->rsn_ie_len) {
211 char buf[MAX_WPA_IE_LEN];
212 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
213 iwe.cmd = IWEVGENIE;
214 iwe.u.data.length = network->rsn_ie_len;
215 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
216 }
217
218 /* Add EXTRA: Age to display seconds since last beacon/probe response
219 * for given network. */
220 iwe.cmd = IWEVCUSTOM;
221 p = custom;
222 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
223 " Last beacon: %dms ago",
224 jiffies_to_msecs(jiffies - network->last_scanned));
225 iwe.u.data.length = p - custom;
226 if (iwe.u.data.length)
227 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
228
229 /* Add spectrum management information */
230 iwe.cmd = -1;
231 p = custom;
232 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
233
234 if (ieee80211_get_channel_flags(ieee, network->channel) &
235 IEEE80211_CH_INVALID) {
236 iwe.cmd = IWEVCUSTOM;
237 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
238 }
239
240 if (ieee80211_get_channel_flags(ieee, network->channel) &
241 IEEE80211_CH_RADAR_DETECT) {
242 iwe.cmd = IWEVCUSTOM;
243 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
244 }
245
246 if (iwe.cmd == IWEVCUSTOM) {
247 iwe.u.data.length = p - custom;
248 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
249 }
250
251 return start;
252}
253
254#define SCAN_ITEM_SIZE 128
255
256int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
257 struct iw_request_info *info,
258 union iwreq_data *wrqu, char *extra)
259{
260 struct ieee80211_network *network;
261 unsigned long flags;
262 int err = 0;
263
264 char *ev = extra;
265 char *stop = ev + wrqu->data.length;
266 int i = 0;
267 DECLARE_MAC_BUF(mac);
268
269 IEEE80211_DEBUG_WX("Getting scan\n");
270
271 spin_lock_irqsave(&ieee->lock, flags);
272
273 list_for_each_entry(network, &ieee->network_list, list) {
274 i++;
275 if (stop - ev < SCAN_ITEM_SIZE) {
276 err = -E2BIG;
277 break;
278 }
279
280 if (ieee->scan_age == 0 ||
281 time_after(network->last_scanned + ieee->scan_age, jiffies))
282 ev = ieee80211_translate_scan(ieee, ev, stop, network,
283 info);
284 else
285 IEEE80211_DEBUG_SCAN("Not showing network '%s ("
286 "%s)' due to age (%dms).\n",
287 escape_essid(network->ssid,
288 network->ssid_len),
289 print_mac(mac, network->bssid),
290 jiffies_to_msecs(jiffies -
291 network->
292 last_scanned));
293 }
294
295 spin_unlock_irqrestore(&ieee->lock, flags);
296
297 wrqu->data.length = ev - extra;
298 wrqu->data.flags = 0;
299
300 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
301
302 return err;
303}
304
305int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
306 struct iw_request_info *info,
307 union iwreq_data *wrqu, char *keybuf)
308{
309 struct iw_point *erq = &(wrqu->encoding);
310 struct net_device *dev = ieee->dev;
311 struct ieee80211_security sec = {
312 .flags = 0
313 };
314 int i, key, key_provided, len;
315 struct ieee80211_crypt_data **crypt;
316 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
317
318 IEEE80211_DEBUG_WX("SET_ENCODE\n");
319
320 key = erq->flags & IW_ENCODE_INDEX;
321 if (key) {
322 if (key > WEP_KEYS)
323 return -EINVAL;
324 key--;
325 key_provided = 1;
326 } else {
327 key_provided = 0;
328 key = ieee->tx_keyidx;
329 }
330
331 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
332 "provided" : "default");
333
334 crypt = &ieee->crypt[key];
335
336 if (erq->flags & IW_ENCODE_DISABLED) {
337 if (key_provided && *crypt) {
338 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
339 key);
340 ieee80211_crypt_delayed_deinit(ieee, crypt);
341 } else
342 IEEE80211_DEBUG_WX("Disabling encryption.\n");
343
344 /* Check all the keys to see if any are still configured,
345 * and if no key index was provided, de-init them all */
346 for (i = 0; i < WEP_KEYS; i++) {
347 if (ieee->crypt[i] != NULL) {
348 if (key_provided)
349 break;
350 ieee80211_crypt_delayed_deinit(ieee,
351 &ieee->crypt[i]);
352 }
353 }
354
355 if (i == WEP_KEYS) {
356 sec.enabled = 0;
357 sec.encrypt = 0;
358 sec.level = SEC_LEVEL_0;
359 sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
360 }
361
362 goto done;
363 }
364
365 sec.enabled = 1;
366 sec.encrypt = 1;
367 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
368
369 if (*crypt != NULL && (*crypt)->ops != NULL &&
370 strcmp((*crypt)->ops->name, "WEP") != 0) {
371 /* changing to use WEP; deinit previously used algorithm
372 * on this key */
373 ieee80211_crypt_delayed_deinit(ieee, crypt);
374 }
375
376 if (*crypt == NULL && host_crypto) {
377 struct ieee80211_crypt_data *new_crypt;
378
379 /* take WEP into use */
380 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
381 GFP_KERNEL);
382 if (new_crypt == NULL)
383 return -ENOMEM;
384 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
385 if (!new_crypt->ops) {
386 request_module("ieee80211_crypt_wep");
387 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
388 }
389
390 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
391 new_crypt->priv = new_crypt->ops->init(key);
392
393 if (!new_crypt->ops || !new_crypt->priv) {
394 kfree(new_crypt);
395 new_crypt = NULL;
396
397 printk(KERN_WARNING "%s: could not initialize WEP: "
398 "load module ieee80211_crypt_wep\n", dev->name);
399 return -EOPNOTSUPP;
400 }
401 *crypt = new_crypt;
402 }
403
404 /* If a new key was provided, set it up */
405 if (erq->length > 0) {
406 len = erq->length <= 5 ? 5 : 13;
407 memcpy(sec.keys[key], keybuf, erq->length);
408 if (len > erq->length)
409 memset(sec.keys[key] + erq->length, 0,
410 len - erq->length);
411 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
412 key, escape_essid(sec.keys[key], len),
413 erq->length, len);
414 sec.key_sizes[key] = len;
415 if (*crypt)
416 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
417 (*crypt)->priv);
418 sec.flags |= (1 << key);
419 /* This ensures a key will be activated if no key is
420 * explicitly set */
421 if (key == sec.active_key)
422 sec.flags |= SEC_ACTIVE_KEY;
423
424 } else {
425 if (host_crypto) {
426 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
427 NULL, (*crypt)->priv);
428 if (len == 0) {
429 /* Set a default key of all 0 */
430 IEEE80211_DEBUG_WX("Setting key %d to all "
431 "zero.\n", key);
432 memset(sec.keys[key], 0, 13);
433 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
434 (*crypt)->priv);
435 sec.key_sizes[key] = 13;
436 sec.flags |= (1 << key);
437 }
438 }
439 /* No key data - just set the default TX key index */
440 if (key_provided) {
441 IEEE80211_DEBUG_WX("Setting key %d to default Tx "
442 "key.\n", key);
443 ieee->tx_keyidx = key;
444 sec.active_key = key;
445 sec.flags |= SEC_ACTIVE_KEY;
446 }
447 }
448 if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
449 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
450 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
451 WLAN_AUTH_SHARED_KEY;
452 sec.flags |= SEC_AUTH_MODE;
453 IEEE80211_DEBUG_WX("Auth: %s\n",
454 sec.auth_mode == WLAN_AUTH_OPEN ?
455 "OPEN" : "SHARED KEY");
456 }
457
458 /* For now we just support WEP, so only set that security level...
459 * TODO: When WPA is added this is one place that needs to change */
460 sec.flags |= SEC_LEVEL;
461 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
462 sec.encode_alg[key] = SEC_ALG_WEP;
463
464 done:
465 if (ieee->set_security)
466 ieee->set_security(dev, &sec);
467
468 /* Do not reset port if card is in Managed mode since resetting will
469 * generate new IEEE 802.11 authentication which may end up in looping
470 * with IEEE 802.1X. If your hardware requires a reset after WEP
471 * configuration (for example... Prism2), implement the reset_port in
472 * the callbacks structures used to initialize the 802.11 stack. */
473 if (ieee->reset_on_keychange &&
474 ieee->iw_mode != IW_MODE_INFRA &&
475 ieee->reset_port && ieee->reset_port(dev)) {
476 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
477 return -EINVAL;
478 }
479 return 0;
480}
481
482int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
483 struct iw_request_info *info,
484 union iwreq_data *wrqu, char *keybuf)
485{
486 struct iw_point *erq = &(wrqu->encoding);
487 int len, key;
488 struct ieee80211_crypt_data *crypt;
489 struct ieee80211_security *sec = &ieee->sec;
490
491 IEEE80211_DEBUG_WX("GET_ENCODE\n");
492
493 key = erq->flags & IW_ENCODE_INDEX;
494 if (key) {
495 if (key > WEP_KEYS)
496 return -EINVAL;
497 key--;
498 } else
499 key = ieee->tx_keyidx;
500
501 crypt = ieee->crypt[key];
502 erq->flags = key + 1;
503
504 if (!sec->enabled) {
505 erq->length = 0;
506 erq->flags |= IW_ENCODE_DISABLED;
507 return 0;
508 }
509
510 len = sec->key_sizes[key];
511 memcpy(keybuf, sec->keys[key], len);
512
513 erq->length = len;
514 erq->flags |= IW_ENCODE_ENABLED;
515
516 if (ieee->open_wep)
517 erq->flags |= IW_ENCODE_OPEN;
518 else
519 erq->flags |= IW_ENCODE_RESTRICTED;
520
521 return 0;
522}
523
524int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
525 struct iw_request_info *info,
526 union iwreq_data *wrqu, char *extra)
527{
528 struct net_device *dev = ieee->dev;
529 struct iw_point *encoding = &wrqu->encoding;
530 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
531 int i, idx, ret = 0;
532 int group_key = 0;
533 const char *alg, *module;
534 struct ieee80211_crypto_ops *ops;
535 struct ieee80211_crypt_data **crypt;
536
537 struct ieee80211_security sec = {
538 .flags = 0,
539 };
540
541 idx = encoding->flags & IW_ENCODE_INDEX;
542 if (idx) {
543 if (idx < 1 || idx > WEP_KEYS)
544 return -EINVAL;
545 idx--;
546 } else
547 idx = ieee->tx_keyidx;
548
549 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
550 crypt = &ieee->crypt[idx];
551 group_key = 1;
552 } else {
553 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
554 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
555 return -EINVAL;
556 if (ieee->iw_mode == IW_MODE_INFRA)
557 crypt = &ieee->crypt[idx];
558 else
559 return -EINVAL;
560 }
561
562 sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
563 if ((encoding->flags & IW_ENCODE_DISABLED) ||
564 ext->alg == IW_ENCODE_ALG_NONE) {
565 if (*crypt)
566 ieee80211_crypt_delayed_deinit(ieee, crypt);
567
568 for (i = 0; i < WEP_KEYS; i++)
569 if (ieee->crypt[i] != NULL)
570 break;
571
572 if (i == WEP_KEYS) {
573 sec.enabled = 0;
574 sec.encrypt = 0;
575 sec.level = SEC_LEVEL_0;
576 sec.flags |= SEC_LEVEL;
577 }
578 goto done;
579 }
580
581 sec.enabled = 1;
582 sec.encrypt = 1;
583
584 if (group_key ? !ieee->host_mc_decrypt :
585 !(ieee->host_encrypt || ieee->host_decrypt ||
586 ieee->host_encrypt_msdu))
587 goto skip_host_crypt;
588
589 switch (ext->alg) {
590 case IW_ENCODE_ALG_WEP:
591 alg = "WEP";
592 module = "ieee80211_crypt_wep";
593 break;
594 case IW_ENCODE_ALG_TKIP:
595 alg = "TKIP";
596 module = "ieee80211_crypt_tkip";
597 break;
598 case IW_ENCODE_ALG_CCMP:
599 alg = "CCMP";
600 module = "ieee80211_crypt_ccmp";
601 break;
602 default:
603 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
604 dev->name, ext->alg);
605 ret = -EINVAL;
606 goto done;
607 }
608
609 ops = ieee80211_get_crypto_ops(alg);
610 if (ops == NULL) {
611 request_module(module);
612 ops = ieee80211_get_crypto_ops(alg);
613 }
614 if (ops == NULL) {
615 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
616 dev->name, ext->alg);
617 ret = -EINVAL;
618 goto done;
619 }
620
621 if (*crypt == NULL || (*crypt)->ops != ops) {
622 struct ieee80211_crypt_data *new_crypt;
623
624 ieee80211_crypt_delayed_deinit(ieee, crypt);
625
626 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
627 if (new_crypt == NULL) {
628 ret = -ENOMEM;
629 goto done;
630 }
631 new_crypt->ops = ops;
632 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
633 new_crypt->priv = new_crypt->ops->init(idx);
634 if (new_crypt->priv == NULL) {
635 kfree(new_crypt);
636 ret = -EINVAL;
637 goto done;
638 }
639 *crypt = new_crypt;
640 }
641
642 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
643 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
644 (*crypt)->priv) < 0) {
645 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
646 ret = -EINVAL;
647 goto done;
648 }
649
650 skip_host_crypt:
651 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
652 ieee->tx_keyidx = idx;
653 sec.active_key = idx;
654 sec.flags |= SEC_ACTIVE_KEY;
655 }
656
657 if (ext->alg != IW_ENCODE_ALG_NONE) {
658 memcpy(sec.keys[idx], ext->key, ext->key_len);
659 sec.key_sizes[idx] = ext->key_len;
660 sec.flags |= (1 << idx);
661 if (ext->alg == IW_ENCODE_ALG_WEP) {
662 sec.encode_alg[idx] = SEC_ALG_WEP;
663 sec.flags |= SEC_LEVEL;
664 sec.level = SEC_LEVEL_1;
665 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
666 sec.encode_alg[idx] = SEC_ALG_TKIP;
667 sec.flags |= SEC_LEVEL;
668 sec.level = SEC_LEVEL_2;
669 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
670 sec.encode_alg[idx] = SEC_ALG_CCMP;
671 sec.flags |= SEC_LEVEL;
672 sec.level = SEC_LEVEL_3;
673 }
674 /* Don't set sec level for group keys. */
675 if (group_key)
676 sec.flags &= ~SEC_LEVEL;
677 }
678 done:
679 if (ieee->set_security)
680 ieee->set_security(ieee->dev, &sec);
681
682 /*
683 * Do not reset port if card is in Managed mode since resetting will
684 * generate new IEEE 802.11 authentication which may end up in looping
685 * with IEEE 802.1X. If your hardware requires a reset after WEP
686 * configuration (for example... Prism2), implement the reset_port in
687 * the callbacks structures used to initialize the 802.11 stack.
688 */
689 if (ieee->reset_on_keychange &&
690 ieee->iw_mode != IW_MODE_INFRA &&
691 ieee->reset_port && ieee->reset_port(dev)) {
692 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
693 return -EINVAL;
694 }
695
696 return ret;
697}
698
699int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
700 struct iw_request_info *info,
701 union iwreq_data *wrqu, char *extra)
702{
703 struct iw_point *encoding = &wrqu->encoding;
704 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
705 struct ieee80211_security *sec = &ieee->sec;
706 int idx, max_key_len;
707
708 max_key_len = encoding->length - sizeof(*ext);
709 if (max_key_len < 0)
710 return -EINVAL;
711
712 idx = encoding->flags & IW_ENCODE_INDEX;
713 if (idx) {
714 if (idx < 1 || idx > WEP_KEYS)
715 return -EINVAL;
716 idx--;
717 } else
718 idx = ieee->tx_keyidx;
719
720 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
721 ext->alg != IW_ENCODE_ALG_WEP)
722 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
723 return -EINVAL;
724
725 encoding->flags = idx + 1;
726 memset(ext, 0, sizeof(*ext));
727
728 if (!sec->enabled) {
729 ext->alg = IW_ENCODE_ALG_NONE;
730 ext->key_len = 0;
731 encoding->flags |= IW_ENCODE_DISABLED;
732 } else {
733 if (sec->encode_alg[idx] == SEC_ALG_WEP)
734 ext->alg = IW_ENCODE_ALG_WEP;
735 else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
736 ext->alg = IW_ENCODE_ALG_TKIP;
737 else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
738 ext->alg = IW_ENCODE_ALG_CCMP;
739 else
740 return -EINVAL;
741
742 ext->key_len = sec->key_sizes[idx];
743 memcpy(ext->key, sec->keys[idx], ext->key_len);
744 encoding->flags |= IW_ENCODE_ENABLED;
745 if (ext->key_len &&
746 (ext->alg == IW_ENCODE_ALG_TKIP ||
747 ext->alg == IW_ENCODE_ALG_CCMP))
748 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
749
750 }
751
752 return 0;
753}
754
755EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
756EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
757
758EXPORT_SYMBOL(ieee80211_wx_get_scan);
759EXPORT_SYMBOL(ieee80211_wx_set_encode);
760EXPORT_SYMBOL(ieee80211_wx_get_encode);