aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-05-12 22:48:20 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-05-12 22:48:20 -0400
commitb453872c35cfcbdbf5a794737817f7d4e7b1b579 (patch)
tree6639da0b12e3f071b57f388c97d28e451f8f3cd3 /net/ieee80211
parentfff9cfd99c0f88645c3f50d7476d6c8cef99f140 (diff)
[NET] ieee80211 subsystem
Contributors: Host AP contributors James Ketrenos <jketreno@linux.intel.com> Francois Romieu <romieu@fr.zoreil.com> Adrian Bunk <bunk@stusta.de> Matthew Galgoci <mgalgoci@parcelfarce.linux.th eplanet.co.uk>
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/Kconfig67
-rw-r--r--net/ieee80211/Makefile11
-rw-r--r--net/ieee80211/ieee80211_crypt.c259
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c470
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c708
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c272
-rw-r--r--net/ieee80211/ieee80211_module.c268
-rw-r--r--net/ieee80211/ieee80211_rx.c1206
-rw-r--r--net/ieee80211/ieee80211_tx.c448
-rw-r--r--net/ieee80211/ieee80211_wx.c471
10 files changed, 4180 insertions, 0 deletions
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
new file mode 100644
index 000000000000..23b23f72a9a4
--- /dev/null
+++ b/net/ieee80211/Kconfig
@@ -0,0 +1,67 @@
1config IEEE80211
2 tristate "Generic IEEE 802.11 Networking Stack"
3 select NET_RADIO
4 ---help---
5 This option enables the hardware independent IEEE 802.11
6 networking stack.
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 CRC32
37 ---help---
38 Include software based cipher suites in support of IEEE
39 802.11's WEP. This is needed for WEP as well as 802.1x.
40
41 This can be compiled as a modules and it will be called
42 "ieee80211_crypt_wep".
43
44config IEEE80211_CRYPT_CCMP
45 tristate "IEEE 802.11i CCMP support"
46 depends on IEEE80211
47 select CRYPTO_AES
48 ---help---
49 Include software based cipher suites in support of IEEE 802.11i
50 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled
51 networks.
52
53 This can be compiled as a modules and it will be called
54 "ieee80211_crypt_ccmp".
55
56config IEEE80211_CRYPT_TKIP
57 tristate "IEEE 802.11i TKIP encryption"
58 depends on IEEE80211
59 select CRYPTO_MICHAEL_MIC
60 ---help---
61 Include software based cipher suites in support of IEEE 802.11i
62 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled
63 networks.
64
65 This can be compiled as a modules and it will be called
66 "ieee80211_crypt_tkip".
67
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
new file mode 100644
index 000000000000..29be9cae1def
--- /dev/null
+++ b/net/ieee80211/Makefile
@@ -0,0 +1,11 @@
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
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
new file mode 100644
index 000000000000..05a6f2f298db
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -0,0 +1,259 @@
1/*
2 * Host AP crypto routines
3 *
4 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.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/config.h>
15#include <linux/version.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <asm/string.h>
20#include <asm/errno.h>
21
22#include <net/ieee80211.h>
23
24MODULE_AUTHOR("Jouni Malinen");
25MODULE_DESCRIPTION("HostAP crypto");
26MODULE_LICENSE("GPL");
27
28struct ieee80211_crypto_alg {
29 struct list_head list;
30 struct ieee80211_crypto_ops *ops;
31};
32
33
34struct ieee80211_crypto {
35 struct list_head algs;
36 spinlock_t lock;
37};
38
39static struct ieee80211_crypto *hcrypt;
40
41void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
42 int force)
43{
44 struct list_head *ptr, *n;
45 struct ieee80211_crypt_data *entry;
46
47 for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
48 ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
49 entry = list_entry(ptr, struct ieee80211_crypt_data, list);
50
51 if (atomic_read(&entry->refcnt) != 0 && !force)
52 continue;
53
54 list_del(ptr);
55
56 if (entry->ops) {
57 entry->ops->deinit(entry->priv);
58 module_put(entry->ops->owner);
59 }
60 kfree(entry);
61 }
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 spin_lock_irqsave(&ieee->lock, flags);
70 ieee80211_crypt_deinit_entries(ieee, 0);
71 if (!list_empty(&ieee->crypt_deinit_list)) {
72 printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
73 "deletion list\n", ieee->dev->name);
74 ieee->crypt_deinit_timer.expires = jiffies + HZ;
75 add_timer(&ieee->crypt_deinit_timer);
76 }
77 spin_unlock_irqrestore(&ieee->lock, flags);
78
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 list_add(&tmp->list, &ieee->crypt_deinit_list);
99 if (!timer_pending(&ieee->crypt_deinit_timer)) {
100 ieee->crypt_deinit_timer.expires = jiffies + HZ;
101 add_timer(&ieee->crypt_deinit_timer);
102 }
103 spin_unlock_irqrestore(&ieee->lock, flags);
104}
105
106int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
107{
108 unsigned long flags;
109 struct ieee80211_crypto_alg *alg;
110
111 if (hcrypt == NULL)
112 return -1;
113
114 alg = kmalloc(sizeof(*alg), GFP_KERNEL);
115 if (alg == NULL)
116 return -ENOMEM;
117
118 memset(alg, 0, sizeof(*alg));
119 alg->ops = ops;
120
121 spin_lock_irqsave(&hcrypt->lock, flags);
122 list_add(&alg->list, &hcrypt->algs);
123 spin_unlock_irqrestore(&hcrypt->lock, flags);
124
125 printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
126 ops->name);
127
128 return 0;
129}
130
131int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
132{
133 unsigned long flags;
134 struct list_head *ptr;
135 struct ieee80211_crypto_alg *del_alg = NULL;
136
137 if (hcrypt == NULL)
138 return -1;
139
140 spin_lock_irqsave(&hcrypt->lock, flags);
141 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
142 struct ieee80211_crypto_alg *alg =
143 (struct ieee80211_crypto_alg *) ptr;
144 if (alg->ops == ops) {
145 list_del(&alg->list);
146 del_alg = alg;
147 break;
148 }
149 }
150 spin_unlock_irqrestore(&hcrypt->lock, flags);
151
152 if (del_alg) {
153 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
154 "'%s'\n", ops->name);
155 kfree(del_alg);
156 }
157
158 return del_alg ? 0 : -1;
159}
160
161
162struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name)
163{
164 unsigned long flags;
165 struct list_head *ptr;
166 struct ieee80211_crypto_alg *found_alg = NULL;
167
168 if (hcrypt == NULL)
169 return NULL;
170
171 spin_lock_irqsave(&hcrypt->lock, flags);
172 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
173 struct ieee80211_crypto_alg *alg =
174 (struct ieee80211_crypto_alg *) ptr;
175 if (strcmp(alg->ops->name, name) == 0) {
176 found_alg = alg;
177 break;
178 }
179 }
180 spin_unlock_irqrestore(&hcrypt->lock, flags);
181
182 if (found_alg)
183 return found_alg->ops;
184 else
185 return NULL;
186}
187
188
189static void * ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
190static void ieee80211_crypt_null_deinit(void *priv) {}
191
192static struct ieee80211_crypto_ops ieee80211_crypt_null = {
193 .name = "NULL",
194 .init = ieee80211_crypt_null_init,
195 .deinit = ieee80211_crypt_null_deinit,
196 .encrypt_mpdu = NULL,
197 .decrypt_mpdu = NULL,
198 .encrypt_msdu = NULL,
199 .decrypt_msdu = NULL,
200 .set_key = NULL,
201 .get_key = NULL,
202 .extra_prefix_len = 0,
203 .extra_postfix_len = 0,
204 .owner = THIS_MODULE,
205};
206
207
208static int __init ieee80211_crypto_init(void)
209{
210 int ret = -ENOMEM;
211
212 hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL);
213 if (!hcrypt)
214 goto out;
215
216 memset(hcrypt, 0, sizeof(*hcrypt));
217 INIT_LIST_HEAD(&hcrypt->algs);
218 spin_lock_init(&hcrypt->lock);
219
220 ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
221 if (ret < 0) {
222 kfree(hcrypt);
223 hcrypt = NULL;
224 }
225out:
226 return ret;
227}
228
229
230static void __exit ieee80211_crypto_deinit(void)
231{
232 struct list_head *ptr, *n;
233
234 if (hcrypt == NULL)
235 return;
236
237 for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
238 ptr = n, n = ptr->next) {
239 struct ieee80211_crypto_alg *alg =
240 (struct ieee80211_crypto_alg *) ptr;
241 list_del(ptr);
242 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
243 "'%s' (deinit)\n", alg->ops->name);
244 kfree(alg);
245 }
246
247 kfree(hcrypt);
248}
249
250EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
251EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
252EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
253
254EXPORT_SYMBOL(ieee80211_register_crypto_ops);
255EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
256EXPORT_SYMBOL(ieee80211_get_crypto_ops);
257
258module_init(ieee80211_crypto_init);
259module_exit(ieee80211_crypto_deinit);
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
new file mode 100644
index 000000000000..f5f412ae7f28
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -0,0 +1,470 @@
1/*
2 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.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/config.h>
13#include <linux/version.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
28#include <linux/crypto.h>
29#include <asm/scatterlist.h>
30
31MODULE_AUTHOR("Jouni Malinen");
32MODULE_DESCRIPTION("Host AP crypt: CCMP");
33MODULE_LICENSE("GPL");
34
35#define AES_BLOCK_LEN 16
36#define CCMP_HDR_LEN 8
37#define CCMP_MIC_LEN 8
38#define CCMP_TK_LEN 16
39#define CCMP_PN_LEN 6
40
41struct ieee80211_ccmp_data {
42 u8 key[CCMP_TK_LEN];
43 int key_set;
44
45 u8 tx_pn[CCMP_PN_LEN];
46 u8 rx_pn[CCMP_PN_LEN];
47
48 u32 dot11RSNAStatsCCMPFormatErrors;
49 u32 dot11RSNAStatsCCMPReplays;
50 u32 dot11RSNAStatsCCMPDecryptErrors;
51
52 int key_idx;
53
54 struct crypto_tfm *tfm;
55
56 /* scratch buffers for virt_to_page() (crypto API) */
57 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
58 tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
59 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
60};
61
62void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
63 const u8 pt[16], u8 ct[16])
64{
65 struct scatterlist src, dst;
66
67 src.page = virt_to_page(pt);
68 src.offset = offset_in_page(pt);
69 src.length = AES_BLOCK_LEN;
70
71 dst.page = virt_to_page(ct);
72 dst.offset = offset_in_page(ct);
73 dst.length = AES_BLOCK_LEN;
74
75 crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
76}
77
78static void * ieee80211_ccmp_init(int key_idx)
79{
80 struct ieee80211_ccmp_data *priv;
81
82 priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
83 if (priv == NULL)
84 goto fail;
85 memset(priv, 0, sizeof(*priv));
86 priv->key_idx = key_idx;
87
88 priv->tfm = crypto_alloc_tfm("aes", 0);
89 if (priv->tfm == NULL) {
90 printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
91 "crypto API aes\n");
92 goto fail;
93 }
94
95 return priv;
96
97fail:
98 if (priv) {
99 if (priv->tfm)
100 crypto_free_tfm(priv->tfm);
101 kfree(priv);
102 }
103
104 return NULL;
105}
106
107
108static void ieee80211_ccmp_deinit(void *priv)
109{
110 struct ieee80211_ccmp_data *_priv = priv;
111 if (_priv && _priv->tfm)
112 crypto_free_tfm(_priv->tfm);
113 kfree(priv);
114}
115
116
117static inline void xor_block(u8 *b, u8 *a, size_t len)
118{
119 int i;
120 for (i = 0; i < len; i++)
121 b[i] ^= a[i];
122}
123
124
125static void ccmp_init_blocks(struct crypto_tfm *tfm,
126 struct ieee80211_hdr *hdr,
127 u8 *pn, size_t dlen, u8 *b0, u8 *auth,
128 u8 *s0)
129{
130 u8 *pos, qc = 0;
131 size_t aad_len;
132 u16 fc;
133 int a4_included, qc_included;
134 u8 aad[2 * AES_BLOCK_LEN];
135
136 fc = le16_to_cpu(hdr->frame_ctl);
137 a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
138 (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
139 qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
140 (WLAN_FC_GET_STYPE(fc) & 0x08));
141 aad_len = 22;
142 if (a4_included)
143 aad_len += 6;
144 if (qc_included) {
145 pos = (u8 *) &hdr->addr4;
146 if (a4_included)
147 pos += 6;
148 qc = *pos & 0x0f;
149 aad_len += 2;
150 }
151
152 /* CCM Initial Block:
153 * Flag (Include authentication header, M=3 (8-octet MIC),
154 * L=1 (2-octet Dlen))
155 * Nonce: 0x00 | A2 | PN
156 * Dlen */
157 b0[0] = 0x59;
158 b0[1] = qc;
159 memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
160 memcpy(b0 + 8, pn, CCMP_PN_LEN);
161 b0[14] = (dlen >> 8) & 0xff;
162 b0[15] = dlen & 0xff;
163
164 /* AAD:
165 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
166 * A1 | A2 | A3
167 * SC with bits 4..15 (seq#) masked to zero
168 * A4 (if present)
169 * QC (if present)
170 */
171 pos = (u8 *) hdr;
172 aad[0] = 0; /* aad_len >> 8 */
173 aad[1] = aad_len & 0xff;
174 aad[2] = pos[0] & 0x8f;
175 aad[3] = pos[1] & 0xc7;
176 memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
177 pos = (u8 *) &hdr->seq_ctl;
178 aad[22] = pos[0] & 0x0f;
179 aad[23] = 0; /* all bits masked */
180 memset(aad + 24, 0, 8);
181 if (a4_included)
182 memcpy(aad + 24, hdr->addr4, ETH_ALEN);
183 if (qc_included) {
184 aad[a4_included ? 30 : 24] = qc;
185 /* rest of QC masked */
186 }
187
188 /* Start with the first block and AAD */
189 ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
190 xor_block(auth, aad, AES_BLOCK_LEN);
191 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
192 xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
193 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
194 b0[0] &= 0x07;
195 b0[14] = b0[15] = 0;
196 ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
197}
198
199
200static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
201{
202 struct ieee80211_ccmp_data *key = priv;
203 int data_len, i, blocks, last, len;
204 u8 *pos, *mic;
205 struct ieee80211_hdr *hdr;
206 u8 *b0 = key->tx_b0;
207 u8 *b = key->tx_b;
208 u8 *e = key->tx_e;
209 u8 *s0 = key->tx_s0;
210
211 if (skb_headroom(skb) < CCMP_HDR_LEN ||
212 skb_tailroom(skb) < CCMP_MIC_LEN ||
213 skb->len < hdr_len)
214 return -1;
215
216 data_len = skb->len - hdr_len;
217 pos = skb_push(skb, CCMP_HDR_LEN);
218 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
219 pos += hdr_len;
220 mic = skb_put(skb, CCMP_MIC_LEN);
221
222 i = CCMP_PN_LEN - 1;
223 while (i >= 0) {
224 key->tx_pn[i]++;
225 if (key->tx_pn[i] != 0)
226 break;
227 i--;
228 }
229
230 *pos++ = key->tx_pn[5];
231 *pos++ = key->tx_pn[4];
232 *pos++ = 0;
233 *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
234 *pos++ = key->tx_pn[3];
235 *pos++ = key->tx_pn[2];
236 *pos++ = key->tx_pn[1];
237 *pos++ = key->tx_pn[0];
238
239 hdr = (struct ieee80211_hdr *) skb->data;
240 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
241
242 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
243 last = data_len % AES_BLOCK_LEN;
244
245 for (i = 1; i <= blocks; i++) {
246 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
247 /* Authentication */
248 xor_block(b, pos, len);
249 ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
250 /* Encryption, with counter */
251 b0[14] = (i >> 8) & 0xff;
252 b0[15] = i & 0xff;
253 ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
254 xor_block(pos, e, len);
255 pos += len;
256 }
257
258 for (i = 0; i < CCMP_MIC_LEN; i++)
259 mic[i] = b[i] ^ s0[i];
260
261 return 0;
262}
263
264
265static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
266{
267 struct ieee80211_ccmp_data *key = priv;
268 u8 keyidx, *pos;
269 struct ieee80211_hdr *hdr;
270 u8 *b0 = key->rx_b0;
271 u8 *b = key->rx_b;
272 u8 *a = key->rx_a;
273 u8 pn[6];
274 int i, blocks, last, len;
275 size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
276 u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
277
278 if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
279 key->dot11RSNAStatsCCMPFormatErrors++;
280 return -1;
281 }
282
283 hdr = (struct ieee80211_hdr *) skb->data;
284 pos = skb->data + hdr_len;
285 keyidx = pos[3];
286 if (!(keyidx & (1 << 5))) {
287 if (net_ratelimit()) {
288 printk(KERN_DEBUG "CCMP: received packet without ExtIV"
289 " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
290 }
291 key->dot11RSNAStatsCCMPFormatErrors++;
292 return -2;
293 }
294 keyidx >>= 6;
295 if (key->key_idx != keyidx) {
296 printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
297 "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
298 return -6;
299 }
300 if (!key->key_set) {
301 if (net_ratelimit()) {
302 printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
303 " with keyid=%d that does not have a configured"
304 " key\n", MAC_ARG(hdr->addr2), keyidx);
305 }
306 return -3;
307 }
308
309 pn[0] = pos[7];
310 pn[1] = pos[6];
311 pn[2] = pos[5];
312 pn[3] = pos[4];
313 pn[4] = pos[1];
314 pn[5] = pos[0];
315 pos += 8;
316
317 if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
318 if (net_ratelimit()) {
319 printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
320 " previous PN %02x%02x%02x%02x%02x%02x "
321 "received PN %02x%02x%02x%02x%02x%02x\n",
322 MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
323 MAC_ARG(pn));
324 }
325 key->dot11RSNAStatsCCMPReplays++;
326 return -4;
327 }
328
329 ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
330 xor_block(mic, b, CCMP_MIC_LEN);
331
332 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
333 last = data_len % AES_BLOCK_LEN;
334
335 for (i = 1; i <= blocks; i++) {
336 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
337 /* Decrypt, with counter */
338 b0[14] = (i >> 8) & 0xff;
339 b0[15] = i & 0xff;
340 ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
341 xor_block(pos, b, len);
342 /* Authentication */
343 xor_block(a, pos, len);
344 ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
345 pos += len;
346 }
347
348 if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
349 if (net_ratelimit()) {
350 printk(KERN_DEBUG "CCMP: decrypt failed: STA="
351 MAC_FMT "\n", MAC_ARG(hdr->addr2));
352 }
353 key->dot11RSNAStatsCCMPDecryptErrors++;
354 return -5;
355 }
356
357 memcpy(key->rx_pn, pn, CCMP_PN_LEN);
358
359 /* Remove hdr and MIC */
360 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
361 skb_pull(skb, CCMP_HDR_LEN);
362 skb_trim(skb, skb->len - CCMP_MIC_LEN);
363
364 return keyidx;
365}
366
367
368static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
369{
370 struct ieee80211_ccmp_data *data = priv;
371 int keyidx;
372 struct crypto_tfm *tfm = data->tfm;
373
374 keyidx = data->key_idx;
375 memset(data, 0, sizeof(*data));
376 data->key_idx = keyidx;
377 data->tfm = tfm;
378 if (len == CCMP_TK_LEN) {
379 memcpy(data->key, key, CCMP_TK_LEN);
380 data->key_set = 1;
381 if (seq) {
382 data->rx_pn[0] = seq[5];
383 data->rx_pn[1] = seq[4];
384 data->rx_pn[2] = seq[3];
385 data->rx_pn[3] = seq[2];
386 data->rx_pn[4] = seq[1];
387 data->rx_pn[5] = seq[0];
388 }
389 crypto_cipher_setkey(data->tfm, data->key, CCMP_TK_LEN);
390 } else if (len == 0)
391 data->key_set = 0;
392 else
393 return -1;
394
395 return 0;
396}
397
398
399static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
400{
401 struct ieee80211_ccmp_data *data = priv;
402
403 if (len < CCMP_TK_LEN)
404 return -1;
405
406 if (!data->key_set)
407 return 0;
408 memcpy(key, data->key, CCMP_TK_LEN);
409
410 if (seq) {
411 seq[0] = data->tx_pn[5];
412 seq[1] = data->tx_pn[4];
413 seq[2] = data->tx_pn[3];
414 seq[3] = data->tx_pn[2];
415 seq[4] = data->tx_pn[1];
416 seq[5] = data->tx_pn[0];
417 }
418
419 return CCMP_TK_LEN;
420}
421
422
423static char * ieee80211_ccmp_print_stats(char *p, void *priv)
424{
425 struct ieee80211_ccmp_data *ccmp = priv;
426 p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
427 "tx_pn=%02x%02x%02x%02x%02x%02x "
428 "rx_pn=%02x%02x%02x%02x%02x%02x "
429 "format_errors=%d replays=%d decrypt_errors=%d\n",
430 ccmp->key_idx, ccmp->key_set,
431 MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
432 ccmp->dot11RSNAStatsCCMPFormatErrors,
433 ccmp->dot11RSNAStatsCCMPReplays,
434 ccmp->dot11RSNAStatsCCMPDecryptErrors);
435
436 return p;
437}
438
439
440static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
441 .name = "CCMP",
442 .init = ieee80211_ccmp_init,
443 .deinit = ieee80211_ccmp_deinit,
444 .encrypt_mpdu = ieee80211_ccmp_encrypt,
445 .decrypt_mpdu = ieee80211_ccmp_decrypt,
446 .encrypt_msdu = NULL,
447 .decrypt_msdu = NULL,
448 .set_key = ieee80211_ccmp_set_key,
449 .get_key = ieee80211_ccmp_get_key,
450 .print_stats = ieee80211_ccmp_print_stats,
451 .extra_prefix_len = CCMP_HDR_LEN,
452 .extra_postfix_len = CCMP_MIC_LEN,
453 .owner = THIS_MODULE,
454};
455
456
457static int __init ieee80211_crypto_ccmp_init(void)
458{
459 return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
460}
461
462
463static void __exit ieee80211_crypto_ccmp_exit(void)
464{
465 ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
466}
467
468
469module_init(ieee80211_crypto_ccmp_init);
470module_exit(ieee80211_crypto_ccmp_exit);
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
new file mode 100644
index 000000000000..f91d92c6df25
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -0,0 +1,708 @@
1/*
2 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.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/config.h>
13#include <linux/version.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
24#include <net/ieee80211.h>
25
26
27#include <linux/crypto.h>
28#include <asm/scatterlist.h>
29#include <linux/crc32.h>
30
31MODULE_AUTHOR("Jouni Malinen");
32MODULE_DESCRIPTION("Host AP crypt: TKIP");
33MODULE_LICENSE("GPL");
34
35struct ieee80211_tkip_data {
36#define TKIP_KEY_LEN 32
37 u8 key[TKIP_KEY_LEN];
38 int key_set;
39
40 u32 tx_iv32;
41 u16 tx_iv16;
42 u16 tx_ttak[5];
43 int tx_phase1_done;
44
45 u32 rx_iv32;
46 u16 rx_iv16;
47 u16 rx_ttak[5];
48 int rx_phase1_done;
49 u32 rx_iv32_new;
50 u16 rx_iv16_new;
51
52 u32 dot11RSNAStatsTKIPReplays;
53 u32 dot11RSNAStatsTKIPICVErrors;
54 u32 dot11RSNAStatsTKIPLocalMICFailures;
55
56 int key_idx;
57
58 struct crypto_tfm *tfm_arc4;
59 struct crypto_tfm *tfm_michael;
60
61 /* scratch buffers for virt_to_page() (crypto API) */
62 u8 rx_hdr[16], tx_hdr[16];
63};
64
65static void * ieee80211_tkip_init(int key_idx)
66{
67 struct ieee80211_tkip_data *priv;
68
69 priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
70 if (priv == NULL)
71 goto fail;
72 memset(priv, 0, sizeof(*priv));
73 priv->key_idx = key_idx;
74
75 priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
76 if (priv->tfm_arc4 == NULL) {
77 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
78 "crypto API arc4\n");
79 goto fail;
80 }
81
82 priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
83 if (priv->tfm_michael == NULL) {
84 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
85 "crypto API michael_mic\n");
86 goto fail;
87 }
88
89 return priv;
90
91fail:
92 if (priv) {
93 if (priv->tfm_michael)
94 crypto_free_tfm(priv->tfm_michael);
95 if (priv->tfm_arc4)
96 crypto_free_tfm(priv->tfm_arc4);
97 kfree(priv);
98 }
99
100 return NULL;
101}
102
103
104static void ieee80211_tkip_deinit(void *priv)
105{
106 struct ieee80211_tkip_data *_priv = priv;
107 if (_priv && _priv->tfm_michael)
108 crypto_free_tfm(_priv->tfm_michael);
109 if (_priv && _priv->tfm_arc4)
110 crypto_free_tfm(_priv->tfm_arc4);
111 kfree(priv);
112}
113
114
115static inline u16 RotR1(u16 val)
116{
117 return (val >> 1) | (val << 15);
118}
119
120
121static inline u8 Lo8(u16 val)
122{
123 return val & 0xff;
124}
125
126
127static inline u8 Hi8(u16 val)
128{
129 return val >> 8;
130}
131
132
133static inline u16 Lo16(u32 val)
134{
135 return val & 0xffff;
136}
137
138
139static inline u16 Hi16(u32 val)
140{
141 return val >> 16;
142}
143
144
145static inline u16 Mk16(u8 hi, u8 lo)
146{
147 return lo | (((u16) hi) << 8);
148}
149
150
151static inline u16 Mk16_le(u16 *v)
152{
153 return le16_to_cpu(*v);
154}
155
156
157static const u16 Sbox[256] =
158{
159 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
160 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
161 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
162 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
163 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
164 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
165 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
166 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
167 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
168 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
169 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
170 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
171 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
172 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
173 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
174 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
175 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
176 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
177 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
178 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
179 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
180 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
181 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
182 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
183 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
184 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
185 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
186 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
187 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
188 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
189 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
190 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
191};
192
193
194static inline u16 _S_(u16 v)
195{
196 u16 t = Sbox[Hi8(v)];
197 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
198}
199
200
201#define PHASE1_LOOP_COUNT 8
202
203static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
204{
205 int i, j;
206
207 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
208 TTAK[0] = Lo16(IV32);
209 TTAK[1] = Hi16(IV32);
210 TTAK[2] = Mk16(TA[1], TA[0]);
211 TTAK[3] = Mk16(TA[3], TA[2]);
212 TTAK[4] = Mk16(TA[5], TA[4]);
213
214 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
215 j = 2 * (i & 1);
216 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
217 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
218 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
219 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
220 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
221 }
222}
223
224
225static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
226 u16 IV16)
227{
228 /* Make temporary area overlap WEP seed so that the final copy can be
229 * avoided on little endian hosts. */
230 u16 *PPK = (u16 *) &WEPSeed[4];
231
232 /* Step 1 - make copy of TTAK and bring in TSC */
233 PPK[0] = TTAK[0];
234 PPK[1] = TTAK[1];
235 PPK[2] = TTAK[2];
236 PPK[3] = TTAK[3];
237 PPK[4] = TTAK[4];
238 PPK[5] = TTAK[4] + IV16;
239
240 /* Step 2 - 96-bit bijective mixing using S-box */
241 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
242 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
243 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
244 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
245 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
246 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
247
248 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
249 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
250 PPK[2] += RotR1(PPK[1]);
251 PPK[3] += RotR1(PPK[2]);
252 PPK[4] += RotR1(PPK[3]);
253 PPK[5] += RotR1(PPK[4]);
254
255 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
256 * WEPSeed[0..2] is transmitted as WEP IV */
257 WEPSeed[0] = Hi8(IV16);
258 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
259 WEPSeed[2] = Lo8(IV16);
260 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
261
262#ifdef __BIG_ENDIAN
263 {
264 int i;
265 for (i = 0; i < 6; i++)
266 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
267 }
268#endif
269}
270
271static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
272{
273 struct ieee80211_tkip_data *tkey = priv;
274 int len;
275 u8 rc4key[16], *pos, *icv;
276 struct ieee80211_hdr *hdr;
277 u32 crc;
278 struct scatterlist sg;
279
280 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
281 skb->len < hdr_len)
282 return -1;
283
284 hdr = (struct ieee80211_hdr *) skb->data;
285 if (!tkey->tx_phase1_done) {
286 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
287 tkey->tx_iv32);
288 tkey->tx_phase1_done = 1;
289 }
290 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
291
292 len = skb->len - hdr_len;
293 pos = skb_push(skb, 8);
294 memmove(pos, pos + 8, hdr_len);
295 pos += hdr_len;
296 icv = skb_put(skb, 4);
297
298 *pos++ = rc4key[0];
299 *pos++ = rc4key[1];
300 *pos++ = rc4key[2];
301 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
302 *pos++ = tkey->tx_iv32 & 0xff;
303 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
304 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
305 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
306
307 crc = ~crc32_le(~0, pos, len);
308 icv[0] = crc;
309 icv[1] = crc >> 8;
310 icv[2] = crc >> 16;
311 icv[3] = crc >> 24;
312
313 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
314 sg.page = virt_to_page(pos);
315 sg.offset = offset_in_page(pos);
316 sg.length = len + 4;
317 crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
318
319 tkey->tx_iv16++;
320 if (tkey->tx_iv16 == 0) {
321 tkey->tx_phase1_done = 0;
322 tkey->tx_iv32++;
323 }
324
325 return 0;
326}
327
328static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
329{
330 struct ieee80211_tkip_data *tkey = priv;
331 u8 rc4key[16];
332 u8 keyidx, *pos;
333 u32 iv32;
334 u16 iv16;
335 struct ieee80211_hdr *hdr;
336 u8 icv[4];
337 u32 crc;
338 struct scatterlist sg;
339 int plen;
340
341 if (skb->len < hdr_len + 8 + 4)
342 return -1;
343
344 hdr = (struct ieee80211_hdr *) skb->data;
345 pos = skb->data + hdr_len;
346 keyidx = pos[3];
347 if (!(keyidx & (1 << 5))) {
348 if (net_ratelimit()) {
349 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
350 " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
351 }
352 return -2;
353 }
354 keyidx >>= 6;
355 if (tkey->key_idx != keyidx) {
356 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
357 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
358 return -6;
359 }
360 if (!tkey->key_set) {
361 if (net_ratelimit()) {
362 printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
363 " with keyid=%d that does not have a configured"
364 " key\n", MAC_ARG(hdr->addr2), keyidx);
365 }
366 return -3;
367 }
368 iv16 = (pos[0] << 8) | pos[2];
369 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
370 pos += 8;
371
372 if (iv32 < tkey->rx_iv32 ||
373 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
374 if (net_ratelimit()) {
375 printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
376 " previous TSC %08x%04x received TSC "
377 "%08x%04x\n", MAC_ARG(hdr->addr2),
378 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
379 }
380 tkey->dot11RSNAStatsTKIPReplays++;
381 return -4;
382 }
383
384 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
385 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
386 tkey->rx_phase1_done = 1;
387 }
388 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
389
390 plen = skb->len - hdr_len - 12;
391
392 crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
393 sg.page = virt_to_page(pos);
394 sg.offset = offset_in_page(pos);
395 sg.length = plen + 4;
396 crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
397
398 crc = ~crc32_le(~0, pos, plen);
399 icv[0] = crc;
400 icv[1] = crc >> 8;
401 icv[2] = crc >> 16;
402 icv[3] = crc >> 24;
403 if (memcmp(icv, pos + plen, 4) != 0) {
404 if (iv32 != tkey->rx_iv32) {
405 /* Previously cached Phase1 result was already lost, so
406 * it needs to be recalculated for the next packet. */
407 tkey->rx_phase1_done = 0;
408 }
409 if (net_ratelimit()) {
410 printk(KERN_DEBUG "TKIP: ICV error detected: STA="
411 MAC_FMT "\n", MAC_ARG(hdr->addr2));
412 }
413 tkey->dot11RSNAStatsTKIPICVErrors++;
414 return -5;
415 }
416
417 /* Update real counters only after Michael MIC verification has
418 * completed */
419 tkey->rx_iv32_new = iv32;
420 tkey->rx_iv16_new = iv16;
421
422 /* Remove IV and ICV */
423 memmove(skb->data + 8, skb->data, hdr_len);
424 skb_pull(skb, 8);
425 skb_trim(skb, skb->len - 4);
426
427 return keyidx;
428}
429
430
431static int michael_mic(struct ieee80211_tkip_data *tkey, u8 *key, u8 *hdr,
432 u8 *data, size_t data_len, u8 *mic)
433{
434 struct scatterlist sg[2];
435
436 if (tkey->tfm_michael == NULL) {
437 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
438 return -1;
439 }
440 sg[0].page = virt_to_page(hdr);
441 sg[0].offset = offset_in_page(hdr);
442 sg[0].length = 16;
443
444 sg[1].page = virt_to_page(data);
445 sg[1].offset = offset_in_page(data);
446 sg[1].length = data_len;
447
448 crypto_digest_init(tkey->tfm_michael);
449 crypto_digest_setkey(tkey->tfm_michael, key, 8);
450 crypto_digest_update(tkey->tfm_michael, sg, 2);
451 crypto_digest_final(tkey->tfm_michael, mic);
452
453 return 0;
454}
455
456static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
457{
458 struct ieee80211_hdr *hdr11;
459
460 hdr11 = (struct ieee80211_hdr *) skb->data;
461 switch (le16_to_cpu(hdr11->frame_ctl) &
462 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
463 case IEEE80211_FCTL_TODS:
464 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
465 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
466 break;
467 case IEEE80211_FCTL_FROMDS:
468 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
469 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
470 break;
471 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
472 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
473 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
474 break;
475 case 0:
476 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
477 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
478 break;
479 }
480
481 hdr[12] = 0; /* priority */
482 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
483}
484
485
486static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
487{
488 struct ieee80211_tkip_data *tkey = priv;
489 u8 *pos;
490
491 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
492 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
493 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
494 skb_tailroom(skb), hdr_len, skb->len);
495 return -1;
496 }
497
498 michael_mic_hdr(skb, tkey->tx_hdr);
499 pos = skb_put(skb, 8);
500 if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
501 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
502 return -1;
503
504 return 0;
505}
506
507
508#if WIRELESS_EXT >= 18
509static void ieee80211_michael_mic_failure(struct net_device *dev,
510 struct ieee80211_hdr *hdr,
511 int keyidx)
512{
513 union iwreq_data wrqu;
514 struct iw_michaelmicfailure ev;
515
516 /* TODO: needed parameters: count, keyid, key type, TSC */
517 memset(&ev, 0, sizeof(ev));
518 ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
519 if (hdr->addr1[0] & 0x01)
520 ev.flags |= IW_MICFAILURE_GROUP;
521 else
522 ev.flags |= IW_MICFAILURE_PAIRWISE;
523 ev.src_addr.sa_family = ARPHRD_ETHER;
524 memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
525 memset(&wrqu, 0, sizeof(wrqu));
526 wrqu.data.length = sizeof(ev);
527 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
528}
529#elif WIRELESS_EXT >= 15
530static void ieee80211_michael_mic_failure(struct net_device *dev,
531 struct ieee80211_hdr *hdr,
532 int keyidx)
533{
534 union iwreq_data wrqu;
535 char buf[128];
536
537 /* TODO: needed parameters: count, keyid, key type, TSC */
538 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
539 MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
540 MAC_ARG(hdr->addr2));
541 memset(&wrqu, 0, sizeof(wrqu));
542 wrqu.data.length = strlen(buf);
543 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
544}
545#else /* WIRELESS_EXT >= 15 */
546static inline void ieee80211_michael_mic_failure(struct net_device *dev,
547 struct ieee80211_hdr *hdr,
548 int keyidx)
549{
550}
551#endif /* WIRELESS_EXT >= 15 */
552
553
554static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
555 int hdr_len, void *priv)
556{
557 struct ieee80211_tkip_data *tkey = priv;
558 u8 mic[8];
559
560 if (!tkey->key_set)
561 return -1;
562
563 michael_mic_hdr(skb, tkey->rx_hdr);
564 if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
565 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
566 return -1;
567 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
568 struct ieee80211_hdr *hdr;
569 hdr = (struct ieee80211_hdr *) skb->data;
570 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
571 "MSDU from " MAC_FMT " keyidx=%d\n",
572 skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
573 keyidx);
574 if (skb->dev)
575 ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
576 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
577 return -1;
578 }
579
580 /* Update TSC counters for RX now that the packet verification has
581 * completed. */
582 tkey->rx_iv32 = tkey->rx_iv32_new;
583 tkey->rx_iv16 = tkey->rx_iv16_new;
584
585 skb_trim(skb, skb->len - 8);
586
587 return 0;
588}
589
590
591static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
592{
593 struct ieee80211_tkip_data *tkey = priv;
594 int keyidx;
595 struct crypto_tfm *tfm = tkey->tfm_michael;
596 struct crypto_tfm *tfm2 = tkey->tfm_arc4;
597
598 keyidx = tkey->key_idx;
599 memset(tkey, 0, sizeof(*tkey));
600 tkey->key_idx = keyidx;
601 tkey->tfm_michael = tfm;
602 tkey->tfm_arc4 = tfm2;
603 if (len == TKIP_KEY_LEN) {
604 memcpy(tkey->key, key, TKIP_KEY_LEN);
605 tkey->key_set = 1;
606 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
607 if (seq) {
608 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
609 (seq[3] << 8) | seq[2];
610 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
611 }
612 } else if (len == 0)
613 tkey->key_set = 0;
614 else
615 return -1;
616
617 return 0;
618}
619
620
621static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
622{
623 struct ieee80211_tkip_data *tkey = priv;
624
625 if (len < TKIP_KEY_LEN)
626 return -1;
627
628 if (!tkey->key_set)
629 return 0;
630 memcpy(key, tkey->key, TKIP_KEY_LEN);
631
632 if (seq) {
633 /* Return the sequence number of the last transmitted frame. */
634 u16 iv16 = tkey->tx_iv16;
635 u32 iv32 = tkey->tx_iv32;
636 if (iv16 == 0)
637 iv32--;
638 iv16--;
639 seq[0] = tkey->tx_iv16;
640 seq[1] = tkey->tx_iv16 >> 8;
641 seq[2] = tkey->tx_iv32;
642 seq[3] = tkey->tx_iv32 >> 8;
643 seq[4] = tkey->tx_iv32 >> 16;
644 seq[5] = tkey->tx_iv32 >> 24;
645 }
646
647 return TKIP_KEY_LEN;
648}
649
650
651static char * ieee80211_tkip_print_stats(char *p, void *priv)
652{
653 struct ieee80211_tkip_data *tkip = priv;
654 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
655 "tx_pn=%02x%02x%02x%02x%02x%02x "
656 "rx_pn=%02x%02x%02x%02x%02x%02x "
657 "replays=%d icv_errors=%d local_mic_failures=%d\n",
658 tkip->key_idx, tkip->key_set,
659 (tkip->tx_iv32 >> 24) & 0xff,
660 (tkip->tx_iv32 >> 16) & 0xff,
661 (tkip->tx_iv32 >> 8) & 0xff,
662 tkip->tx_iv32 & 0xff,
663 (tkip->tx_iv16 >> 8) & 0xff,
664 tkip->tx_iv16 & 0xff,
665 (tkip->rx_iv32 >> 24) & 0xff,
666 (tkip->rx_iv32 >> 16) & 0xff,
667 (tkip->rx_iv32 >> 8) & 0xff,
668 tkip->rx_iv32 & 0xff,
669 (tkip->rx_iv16 >> 8) & 0xff,
670 tkip->rx_iv16 & 0xff,
671 tkip->dot11RSNAStatsTKIPReplays,
672 tkip->dot11RSNAStatsTKIPICVErrors,
673 tkip->dot11RSNAStatsTKIPLocalMICFailures);
674 return p;
675}
676
677
678static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
679 .name = "TKIP",
680 .init = ieee80211_tkip_init,
681 .deinit = ieee80211_tkip_deinit,
682 .encrypt_mpdu = ieee80211_tkip_encrypt,
683 .decrypt_mpdu = ieee80211_tkip_decrypt,
684 .encrypt_msdu = ieee80211_michael_mic_add,
685 .decrypt_msdu = ieee80211_michael_mic_verify,
686 .set_key = ieee80211_tkip_set_key,
687 .get_key = ieee80211_tkip_get_key,
688 .print_stats = ieee80211_tkip_print_stats,
689 .extra_prefix_len = 4 + 4, /* IV + ExtIV */
690 .extra_postfix_len = 8 + 4, /* MIC + ICV */
691 .owner = THIS_MODULE,
692};
693
694
695static int __init ieee80211_crypto_tkip_init(void)
696{
697 return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
698}
699
700
701static void __exit ieee80211_crypto_tkip_exit(void)
702{
703 ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
704}
705
706
707module_init(ieee80211_crypto_tkip_init);
708module_exit(ieee80211_crypto_tkip_exit);
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
new file mode 100644
index 000000000000..bec1d3470d39
--- /dev/null
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -0,0 +1,272 @@
1/*
2 * Host AP crypt: host-based WEP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.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/config.h>
13#include <linux/version.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 <asm/string.h>
20
21#include <net/ieee80211.h>
22
23
24#include <linux/crypto.h>
25#include <asm/scatterlist.h>
26#include <linux/crc32.h>
27
28MODULE_AUTHOR("Jouni Malinen");
29MODULE_DESCRIPTION("Host AP crypt: WEP");
30MODULE_LICENSE("GPL");
31
32
33struct prism2_wep_data {
34 u32 iv;
35#define WEP_KEY_LEN 13
36 u8 key[WEP_KEY_LEN + 1];
37 u8 key_len;
38 u8 key_idx;
39 struct crypto_tfm *tfm;
40};
41
42
43static void * prism2_wep_init(int keyidx)
44{
45 struct prism2_wep_data *priv;
46
47 priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
48 if (priv == NULL)
49 goto fail;
50 memset(priv, 0, sizeof(*priv));
51 priv->key_idx = keyidx;
52
53 priv->tfm = crypto_alloc_tfm("arc4", 0);
54 if (priv->tfm == NULL) {
55 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
56 "crypto API arc4\n");
57 goto fail;
58 }
59
60 /* start WEP IV from a random value */
61 get_random_bytes(&priv->iv, 4);
62
63 return priv;
64
65fail:
66 if (priv) {
67 if (priv->tfm)
68 crypto_free_tfm(priv->tfm);
69 kfree(priv);
70 }
71 return NULL;
72}
73
74
75static void prism2_wep_deinit(void *priv)
76{
77 struct prism2_wep_data *_priv = priv;
78 if (_priv && _priv->tfm)
79 crypto_free_tfm(_priv->tfm);
80 kfree(priv);
81}
82
83
84/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
85 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
86 * so the payload length increases with 8 bytes.
87 *
88 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
89 */
90static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
91{
92 struct prism2_wep_data *wep = priv;
93 u32 crc, klen, len;
94 u8 key[WEP_KEY_LEN + 3];
95 u8 *pos, *icv;
96 struct scatterlist sg;
97
98 if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
99 skb->len < hdr_len)
100 return -1;
101
102 len = skb->len - hdr_len;
103 pos = skb_push(skb, 4);
104 memmove(pos, pos + 4, hdr_len);
105 pos += hdr_len;
106
107 klen = 3 + wep->key_len;
108
109 wep->iv++;
110
111 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
112 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
113 * can be used to speedup attacks, so avoid using them. */
114 if ((wep->iv & 0xff00) == 0xff00) {
115 u8 B = (wep->iv >> 16) & 0xff;
116 if (B >= 3 && B < klen)
117 wep->iv += 0x0100;
118 }
119
120 /* Prepend 24-bit IV to RC4 key and TX frame */
121 *pos++ = key[0] = (wep->iv >> 16) & 0xff;
122 *pos++ = key[1] = (wep->iv >> 8) & 0xff;
123 *pos++ = key[2] = wep->iv & 0xff;
124 *pos++ = wep->key_idx << 6;
125
126 /* Copy rest of the WEP key (the secret part) */
127 memcpy(key + 3, wep->key, wep->key_len);
128
129 /* Append little-endian CRC32 and encrypt it to produce ICV */
130 crc = ~crc32_le(~0, pos, len);
131 icv = skb_put(skb, 4);
132 icv[0] = crc;
133 icv[1] = crc >> 8;
134 icv[2] = crc >> 16;
135 icv[3] = crc >> 24;
136
137 crypto_cipher_setkey(wep->tfm, key, klen);
138 sg.page = virt_to_page(pos);
139 sg.offset = offset_in_page(pos);
140 sg.length = len + 4;
141 crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
142
143 return 0;
144}
145
146
147/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
148 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
149 * ICV (4 bytes). len includes both IV and ICV.
150 *
151 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
152 * failure. If frame is OK, IV and ICV will be removed.
153 */
154static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
155{
156 struct prism2_wep_data *wep = priv;
157 u32 crc, klen, plen;
158 u8 key[WEP_KEY_LEN + 3];
159 u8 keyidx, *pos, icv[4];
160 struct scatterlist sg;
161
162 if (skb->len < hdr_len + 8)
163 return -1;
164
165 pos = skb->data + hdr_len;
166 key[0] = *pos++;
167 key[1] = *pos++;
168 key[2] = *pos++;
169 keyidx = *pos++ >> 6;
170 if (keyidx != wep->key_idx)
171 return -1;
172
173 klen = 3 + wep->key_len;
174
175 /* Copy rest of the WEP key (the secret part) */
176 memcpy(key + 3, wep->key, wep->key_len);
177
178 /* Apply RC4 to data and compute CRC32 over decrypted data */
179 plen = skb->len - hdr_len - 8;
180
181 crypto_cipher_setkey(wep->tfm, key, klen);
182 sg.page = virt_to_page(pos);
183 sg.offset = offset_in_page(pos);
184 sg.length = plen + 4;
185 crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4);
186
187 crc = ~crc32_le(~0, pos, plen);
188 icv[0] = crc;
189 icv[1] = crc >> 8;
190 icv[2] = crc >> 16;
191 icv[3] = crc >> 24;
192 if (memcmp(icv, pos + plen, 4) != 0) {
193 /* ICV mismatch - drop frame */
194 return -2;
195 }
196
197 /* Remove IV and ICV */
198 memmove(skb->data + 4, skb->data, hdr_len);
199 skb_pull(skb, 4);
200 skb_trim(skb, skb->len - 4);
201
202 return 0;
203}
204
205
206static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
207{
208 struct prism2_wep_data *wep = priv;
209
210 if (len < 0 || len > WEP_KEY_LEN)
211 return -1;
212
213 memcpy(wep->key, key, len);
214 wep->key_len = len;
215
216 return 0;
217}
218
219
220static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
221{
222 struct prism2_wep_data *wep = priv;
223
224 if (len < wep->key_len)
225 return -1;
226
227 memcpy(key, wep->key, wep->key_len);
228
229 return wep->key_len;
230}
231
232
233static char * prism2_wep_print_stats(char *p, void *priv)
234{
235 struct prism2_wep_data *wep = priv;
236 p += sprintf(p, "key[%d] alg=WEP len=%d\n",
237 wep->key_idx, wep->key_len);
238 return p;
239}
240
241
242static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
243 .name = "WEP",
244 .init = prism2_wep_init,
245 .deinit = prism2_wep_deinit,
246 .encrypt_mpdu = prism2_wep_encrypt,
247 .decrypt_mpdu = prism2_wep_decrypt,
248 .encrypt_msdu = NULL,
249 .decrypt_msdu = NULL,
250 .set_key = prism2_wep_set_key,
251 .get_key = prism2_wep_get_key,
252 .print_stats = prism2_wep_print_stats,
253 .extra_prefix_len = 4, /* IV */
254 .extra_postfix_len = 4, /* ICV */
255 .owner = THIS_MODULE,
256};
257
258
259static int __init ieee80211_crypto_wep_init(void)
260{
261 return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
262}
263
264
265static void __exit ieee80211_crypto_wep_exit(void)
266{
267 ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
268}
269
270
271module_init(ieee80211_crypto_wep_init);
272module_exit(ieee80211_crypto_wep_exit);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
new file mode 100644
index 000000000000..e4ca0daaaeea
--- /dev/null
+++ b/net/ieee80211/ieee80211_module.c
@@ -0,0 +1,268 @@
1/*******************************************************************************
2
3 Copyright(c) 2004 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 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.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/config.h>
35#include <linux/errno.h>
36#include <linux/if_arp.h>
37#include <linux/in6.h>
38#include <linux/in.h>
39#include <linux/ip.h>
40#include <linux/kernel.h>
41#include <linux/module.h>
42#include <linux/netdevice.h>
43#include <linux/pci.h>
44#include <linux/proc_fs.h>
45#include <linux/skbuff.h>
46#include <linux/slab.h>
47#include <linux/tcp.h>
48#include <linux/types.h>
49#include <linux/version.h>
50#include <linux/wireless.h>
51#include <linux/etherdevice.h>
52#include <asm/uaccess.h>
53#include <net/arp.h>
54
55#include <net/ieee80211.h>
56
57MODULE_DESCRIPTION("802.11 data/management/control stack");
58MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
59MODULE_LICENSE("GPL");
60
61#define DRV_NAME "ieee80211"
62
63static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
64{
65 if (ieee->networks)
66 return 0;
67
68 ieee->networks = kmalloc(
69 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
70 GFP_KERNEL);
71 if (!ieee->networks) {
72 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
73 ieee->dev->name);
74 return -ENOMEM;
75 }
76
77 memset(ieee->networks, 0,
78 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
79
80 return 0;
81}
82
83static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
84{
85 if (!ieee->networks)
86 return;
87 kfree(ieee->networks);
88 ieee->networks = NULL;
89}
90
91static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
92{
93 int i;
94
95 INIT_LIST_HEAD(&ieee->network_free_list);
96 INIT_LIST_HEAD(&ieee->network_list);
97 for (i = 0; i < MAX_NETWORK_COUNT; i++)
98 list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
99}
100
101
102struct net_device *alloc_ieee80211(int sizeof_priv)
103{
104 struct ieee80211_device *ieee;
105 struct net_device *dev;
106 int err;
107
108 IEEE80211_DEBUG_INFO("Initializing...\n");
109
110 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
111 if (!dev) {
112 IEEE80211_ERROR("Unable to network device.\n");
113 goto failed;
114 }
115 ieee = netdev_priv(dev);
116 dev->hard_start_xmit = ieee80211_xmit;
117
118 ieee->dev = dev;
119
120 err = ieee80211_networks_allocate(ieee);
121 if (err) {
122 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
123 err);
124 goto failed;
125 }
126 ieee80211_networks_initialize(ieee);
127
128 /* Default fragmentation threshold is maximum payload size */
129 ieee->fts = DEFAULT_FTS;
130 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
131 ieee->open_wep = 1;
132
133 /* Default to enabling full open WEP with host based encrypt/decrypt */
134 ieee->host_encrypt = 1;
135 ieee->host_decrypt = 1;
136 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
137
138 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
139 init_timer(&ieee->crypt_deinit_timer);
140 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
141 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
142
143 spin_lock_init(&ieee->lock);
144
145 ieee->wpa_enabled = 0;
146 ieee->tkip_countermeasures = 0;
147 ieee->drop_unencrypted = 0;
148 ieee->privacy_invoked = 0;
149 ieee->ieee802_1x = 1;
150
151 return dev;
152
153 failed:
154 if (dev)
155 free_netdev(dev);
156 return NULL;
157}
158
159
160void free_ieee80211(struct net_device *dev)
161{
162 struct ieee80211_device *ieee = netdev_priv(dev);
163
164 int i;
165
166 del_timer_sync(&ieee->crypt_deinit_timer);
167 ieee80211_crypt_deinit_entries(ieee, 1);
168
169 for (i = 0; i < WEP_KEYS; i++) {
170 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
171 if (crypt) {
172 if (crypt->ops) {
173 crypt->ops->deinit(crypt->priv);
174 module_put(crypt->ops->owner);
175 }
176 kfree(crypt);
177 ieee->crypt[i] = NULL;
178 }
179 }
180
181 ieee80211_networks_free(ieee);
182 free_netdev(dev);
183}
184
185#ifdef CONFIG_IEEE80211_DEBUG
186
187static int debug = 0;
188u32 ieee80211_debug_level = 0;
189struct proc_dir_entry *ieee80211_proc = NULL;
190
191static int show_debug_level(char *page, char **start, off_t offset,
192 int count, int *eof, void *data)
193{
194 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
195}
196
197static int store_debug_level(struct file *file, const char *buffer,
198 unsigned long count, void *data)
199{
200 char buf[] = "0x00000000";
201 unsigned long len = min(sizeof(buf) - 1, (u32)count);
202 char *p = (char *)buf;
203 unsigned long val;
204
205 if (copy_from_user(buf, buffer, len))
206 return count;
207 buf[len] = 0;
208 if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
209 p++;
210 if (p[0] == 'x' || p[0] == 'X')
211 p++;
212 val = simple_strtoul(p, &p, 16);
213 } else
214 val = simple_strtoul(p, &p, 10);
215 if (p == buf)
216 printk(KERN_INFO DRV_NAME
217 ": %s is not in hex or decimal form.\n", buf);
218 else
219 ieee80211_debug_level = val;
220
221 return strnlen(buf, count);
222}
223
224static int __init ieee80211_init(void)
225{
226 struct proc_dir_entry *e;
227
228 ieee80211_debug_level = debug;
229 ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
230 if (ieee80211_proc == NULL) {
231 IEEE80211_ERROR("Unable to create " DRV_NAME
232 " proc directory\n");
233 return -EIO;
234 }
235 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
236 ieee80211_proc);
237 if (!e) {
238 remove_proc_entry(DRV_NAME, proc_net);
239 ieee80211_proc = NULL;
240 return -EIO;
241 }
242 e->read_proc = show_debug_level;
243 e->write_proc = store_debug_level;
244 e->data = NULL;
245
246 return 0;
247}
248
249static void __exit ieee80211_exit(void)
250{
251 if (ieee80211_proc) {
252 remove_proc_entry("debug_level", ieee80211_proc);
253 remove_proc_entry(DRV_NAME, proc_net);
254 ieee80211_proc = NULL;
255 }
256}
257
258#include <linux/moduleparam.h>
259module_param(debug, int, 0444);
260MODULE_PARM_DESC(debug, "debug output mask");
261
262
263module_exit(ieee80211_exit);
264module_init(ieee80211_init);
265#endif
266
267EXPORT_SYMBOL(alloc_ieee80211);
268EXPORT_SYMBOL(free_ieee80211);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
new file mode 100644
index 000000000000..2bda8a174818
--- /dev/null
+++ b/net/ieee80211/ieee80211_rx.c
@@ -0,0 +1,1206 @@
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 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Copyright (c) 2004, 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/config.h>
18#include <linux/errno.h>
19#include <linux/if_arp.h>
20#include <linux/in6.h>
21#include <linux/in.h>
22#include <linux/ip.h>
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/netdevice.h>
26#include <linux/pci.h>
27#include <linux/proc_fs.h>
28#include <linux/skbuff.h>
29#include <linux/slab.h>
30#include <linux/tcp.h>
31#include <linux/types.h>
32#include <linux/version.h>
33#include <linux/wireless.h>
34#include <linux/etherdevice.h>
35#include <asm/uaccess.h>
36#include <linux/ctype.h>
37
38#include <net/ieee80211.h>
39
40static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
41 struct sk_buff *skb,
42 struct ieee80211_rx_stats *rx_stats)
43{
44 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
45 u16 fc = le16_to_cpu(hdr->frame_ctl);
46
47 skb->dev = ieee->dev;
48 skb->mac.raw = skb->data;
49 skb_pull(skb, ieee80211_get_hdrlen(fc));
50 skb->pkt_type = PACKET_OTHERHOST;
51 skb->protocol = __constant_htons(ETH_P_80211_RAW);
52 memset(skb->cb, 0, sizeof(skb->cb));
53 netif_rx(skb);
54}
55
56
57/* Called only as a tasklet (software IRQ) */
58static struct ieee80211_frag_entry *
59ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
60 unsigned int frag, u8 *src, 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(
70 "expiring fragment cache entry "
71 "seq=%u last_frag=%u\n",
72 entry->seq, entry->last_frag);
73 dev_kfree_skb_any(entry->skb);
74 entry->skb = NULL;
75 }
76
77 if (entry->skb != NULL && entry->seq == seq &&
78 (entry->last_frag + 1 == frag || frag == -1) &&
79 memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
80 memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
81 return entry;
82 }
83
84 return NULL;
85}
86
87/* Called only as a tasklet (software IRQ) */
88static struct sk_buff *
89ieee80211_frag_cache_get(struct ieee80211_device *ieee,
90 struct ieee80211_hdr *hdr)
91{
92 struct sk_buff *skb = NULL;
93 u16 sc;
94 unsigned int frag, seq;
95 struct ieee80211_frag_entry *entry;
96
97 sc = le16_to_cpu(hdr->seq_ctl);
98 frag = WLAN_GET_SEQ_FRAG(sc);
99 seq = WLAN_GET_SEQ_SEQ(sc);
100
101 if (frag == 0) {
102 /* Reserve enough space to fit maximum frame length */
103 skb = dev_alloc_skb(ieee->dev->mtu +
104 sizeof(struct ieee80211_hdr) +
105 8 /* LLC */ +
106 2 /* alignment */ +
107 8 /* WEP */ + ETH_ALEN /* WDS */);
108 if (skb == NULL)
109 return NULL;
110
111 entry = &ieee->frag_cache[ieee->frag_next_idx];
112 ieee->frag_next_idx++;
113 if (ieee->frag_next_idx >= IEEE80211_FRAG_CACHE_LEN)
114 ieee->frag_next_idx = 0;
115
116 if (entry->skb != NULL)
117 dev_kfree_skb_any(entry->skb);
118
119 entry->first_frag_time = jiffies;
120 entry->seq = seq;
121 entry->last_frag = frag;
122 entry->skb = skb;
123 memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
124 memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
125 } else {
126 /* received a fragment of a frame for which the head fragment
127 * should have already been received */
128 entry = ieee80211_frag_cache_find(ieee, seq, frag, hdr->addr2,
129 hdr->addr1);
130 if (entry != NULL) {
131 entry->last_frag = frag;
132 skb = entry->skb;
133 }
134 }
135
136 return skb;
137}
138
139
140/* Called only as a tasklet (software IRQ) */
141static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
142 struct ieee80211_hdr *hdr)
143{
144 u16 sc;
145 unsigned int seq;
146 struct ieee80211_frag_entry *entry;
147
148 sc = le16_to_cpu(hdr->seq_ctl);
149 seq = WLAN_GET_SEQ_SEQ(sc);
150
151 entry = ieee80211_frag_cache_find(ieee, seq, -1, hdr->addr2,
152 hdr->addr1);
153
154 if (entry == NULL) {
155 IEEE80211_DEBUG_FRAG(
156 "could not invalidate fragment cache "
157 "entry (seq=%u)\n", seq);
158 return -1;
159 }
160
161 entry->skb = NULL;
162 return 0;
163}
164
165
166#ifdef NOT_YET
167/* ieee80211_rx_frame_mgtmt
168 *
169 * Responsible for handling management control frames
170 *
171 * Called by ieee80211_rx */
172static inline int
173ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
174 struct ieee80211_rx_stats *rx_stats, u16 type,
175 u16 stype)
176{
177 if (ieee->iw_mode == IW_MODE_MASTER) {
178 printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
179 ieee->dev->name);
180 return 0;
181/*
182 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *)
183 skb->data);*/
184 }
185
186 if (ieee->hostapd && type == WLAN_FC_TYPE_MGMT) {
187 if (stype == WLAN_FC_STYPE_BEACON &&
188 ieee->iw_mode == IW_MODE_MASTER) {
189 struct sk_buff *skb2;
190 /* Process beacon frames also in kernel driver to
191 * update STA(AP) table statistics */
192 skb2 = skb_clone(skb, GFP_ATOMIC);
193 if (skb2)
194 hostap_rx(skb2->dev, skb2, rx_stats);
195 }
196
197 /* send management frames to the user space daemon for
198 * processing */
199 ieee->apdevstats.rx_packets++;
200 ieee->apdevstats.rx_bytes += skb->len;
201 prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
202 return 0;
203 }
204
205 if (ieee->iw_mode == IW_MODE_MASTER) {
206 if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
207 printk(KERN_DEBUG "%s: unknown management frame "
208 "(type=0x%02x, stype=0x%02x) dropped\n",
209 skb->dev->name, type, stype);
210 return -1;
211 }
212
213 hostap_rx(skb->dev, skb, rx_stats);
214 return 0;
215 }
216
217 printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
218 "received in non-Host AP mode\n", skb->dev->name);
219 return -1;
220}
221#endif
222
223
224/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
225/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
226static unsigned char rfc1042_header[] =
227{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
228/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
229static unsigned char bridge_tunnel_header[] =
230{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
231/* No encapsulation header if EtherType < 0x600 (=length) */
232
233/* Called by ieee80211_rx_frame_decrypt */
234static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
235 struct sk_buff *skb)
236{
237 struct net_device *dev = ieee->dev;
238 u16 fc, ethertype;
239 struct ieee80211_hdr *hdr;
240 u8 *pos;
241
242 if (skb->len < 24)
243 return 0;
244
245 hdr = (struct ieee80211_hdr *) skb->data;
246 fc = le16_to_cpu(hdr->frame_ctl);
247
248 /* check that the frame is unicast frame to us */
249 if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
250 IEEE80211_FCTL_TODS &&
251 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
252 memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
253 /* ToDS frame with own addr BSSID and DA */
254 } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
255 IEEE80211_FCTL_FROMDS &&
256 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
257 /* FromDS frame with own addr as DA */
258 } else
259 return 0;
260
261 if (skb->len < 24 + 8)
262 return 0;
263
264 /* check for port access entity Ethernet type */
265 pos = skb->data + 24;
266 ethertype = (pos[6] << 8) | pos[7];
267 if (ethertype == ETH_P_PAE)
268 return 1;
269
270 return 0;
271}
272
273/* Called only as a tasklet (software IRQ), by ieee80211_rx */
274static inline int
275ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
276 struct ieee80211_crypt_data *crypt)
277{
278 struct ieee80211_hdr *hdr;
279 int res, hdrlen;
280
281 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
282 return 0;
283
284 hdr = (struct ieee80211_hdr *) skb->data;
285 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
286
287#ifdef CONFIG_IEEE80211_CRYPT_TKIP
288 if (ieee->tkip_countermeasures &&
289 strcmp(crypt->ops->name, "TKIP") == 0) {
290 if (net_ratelimit()) {
291 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
292 "received packet from " MAC_FMT "\n",
293 ieee->dev->name, MAC_ARG(hdr->addr2));
294 }
295 return -1;
296 }
297#endif
298
299 atomic_inc(&crypt->refcnt);
300 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
301 atomic_dec(&crypt->refcnt);
302 if (res < 0) {
303 IEEE80211_DEBUG_DROP(
304 "decryption failed (SA=" MAC_FMT
305 ") res=%d\n", MAC_ARG(hdr->addr2), res);
306 if (res == -2)
307 IEEE80211_DEBUG_DROP("Decryption failed ICV "
308 "mismatch (key %d)\n",
309 skb->data[hdrlen + 3] >> 6);
310 ieee->ieee_stats.rx_discards_undecryptable++;
311 return -1;
312 }
313
314 return res;
315}
316
317
318/* Called only as a tasklet (software IRQ), by ieee80211_rx */
319static inline int
320ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
321 int keyidx, struct ieee80211_crypt_data *crypt)
322{
323 struct ieee80211_hdr *hdr;
324 int res, hdrlen;
325
326 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
327 return 0;
328
329 hdr = (struct ieee80211_hdr *) skb->data;
330 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
331
332 atomic_inc(&crypt->refcnt);
333 res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
334 atomic_dec(&crypt->refcnt);
335 if (res < 0) {
336 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
337 " (SA=" MAC_FMT " keyidx=%d)\n",
338 ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
339 return -1;
340 }
341
342 return 0;
343}
344
345
346/* All received frames are sent to this function. @skb contains the frame in
347 * IEEE 802.11 format, i.e., in the format it was sent over air.
348 * This function is called only as a tasklet (software IRQ). */
349int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
350 struct ieee80211_rx_stats *rx_stats)
351{
352 struct net_device *dev = ieee->dev;
353 struct ieee80211_hdr *hdr;
354 size_t hdrlen;
355 u16 fc, type, stype, sc;
356 struct net_device_stats *stats;
357 unsigned int frag;
358 u8 *payload;
359 u16 ethertype;
360#ifdef NOT_YET
361 struct net_device *wds = NULL;
362 struct sk_buff *skb2 = NULL;
363 struct net_device *wds = NULL;
364 int frame_authorized = 0;
365 int from_assoc_ap = 0;
366 void *sta = NULL;
367#endif
368 u8 dst[ETH_ALEN];
369 u8 src[ETH_ALEN];
370 struct ieee80211_crypt_data *crypt = NULL;
371 int keyidx = 0;
372
373 hdr = (struct ieee80211_hdr *)skb->data;
374 stats = &ieee->stats;
375
376 if (skb->len < 10) {
377 printk(KERN_INFO "%s: SKB length < 10\n",
378 dev->name);
379 goto rx_dropped;
380 }
381
382 fc = le16_to_cpu(hdr->frame_ctl);
383 type = WLAN_FC_GET_TYPE(fc);
384 stype = WLAN_FC_GET_STYPE(fc);
385 sc = le16_to_cpu(hdr->seq_ctl);
386 frag = WLAN_GET_SEQ_FRAG(sc);
387 hdrlen = ieee80211_get_hdrlen(fc);
388
389#ifdef NOT_YET
390#if WIRELESS_EXT > 15
391 /* Put this code here so that we avoid duplicating it in all
392 * Rx paths. - Jean II */
393#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
394 /* If spy monitoring on */
395 if (iface->spy_data.spy_number > 0) {
396 struct iw_quality wstats;
397 wstats.level = rx_stats->signal;
398 wstats.noise = rx_stats->noise;
399 wstats.updated = 6; /* No qual value */
400 /* Update spy records */
401 wireless_spy_update(dev, hdr->addr2, &wstats);
402 }
403#endif /* IW_WIRELESS_SPY */
404#endif /* WIRELESS_EXT > 15 */
405 hostap_update_rx_stats(local->ap, hdr, rx_stats);
406#endif
407
408#if WIRELESS_EXT > 15
409 if (ieee->iw_mode == IW_MODE_MONITOR) {
410 ieee80211_monitor_rx(ieee, skb, rx_stats);
411 stats->rx_packets++;
412 stats->rx_bytes += skb->len;
413 return 1;
414 }
415#endif
416
417 if (ieee->host_decrypt) {
418 int idx = 0;
419 if (skb->len >= hdrlen + 3)
420 idx = skb->data[hdrlen + 3] >> 6;
421 crypt = ieee->crypt[idx];
422#ifdef NOT_YET
423 sta = NULL;
424
425 /* Use station specific key to override default keys if the
426 * receiver address is a unicast address ("individual RA"). If
427 * bcrx_sta_key parameter is set, station specific key is used
428 * even with broad/multicast targets (this is against IEEE
429 * 802.11, but makes it easier to use different keys with
430 * stations that do not support WEP key mapping). */
431
432 if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
433 (void) hostap_handle_sta_crypto(local, hdr, &crypt,
434 &sta);
435#endif
436
437 /* allow NULL decrypt to indicate an station specific override
438 * for default encryption */
439 if (crypt && (crypt->ops == NULL ||
440 crypt->ops->decrypt_mpdu == NULL))
441 crypt = NULL;
442
443 if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
444 /* This seems to be triggered by some (multicast?)
445 * frames from other than current BSS, so just drop the
446 * frames silently instead of filling system log with
447 * these reports. */
448 IEEE80211_DEBUG_DROP("Decryption failed (not set)"
449 " (SA=" MAC_FMT ")\n",
450 MAC_ARG(hdr->addr2));
451 ieee->ieee_stats.rx_discards_undecryptable++;
452 goto rx_dropped;
453 }
454 }
455
456#ifdef NOT_YET
457 if (type != WLAN_FC_TYPE_DATA) {
458 if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH &&
459 fc & IEEE80211_FCTL_WEP && ieee->host_decrypt &&
460 (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0)
461 {
462 printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
463 "from " MAC_FMT "\n", dev->name,
464 MAC_ARG(hdr->addr2));
465 /* TODO: could inform hostapd about this so that it
466 * could send auth failure report */
467 goto rx_dropped;
468 }
469
470 if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
471 goto rx_dropped;
472 else
473 goto rx_exit;
474 }
475#endif
476
477 /* Data frame - extract src/dst addresses */
478 if (skb->len < IEEE80211_DATA_HDR3_LEN)
479 goto rx_dropped;
480
481 switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
482 case IEEE80211_FCTL_FROMDS:
483 memcpy(dst, hdr->addr1, ETH_ALEN);
484 memcpy(src, hdr->addr3, ETH_ALEN);
485 break;
486 case IEEE80211_FCTL_TODS:
487 memcpy(dst, hdr->addr3, ETH_ALEN);
488 memcpy(src, hdr->addr2, ETH_ALEN);
489 break;
490 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
491 if (skb->len < IEEE80211_DATA_HDR4_LEN)
492 goto rx_dropped;
493 memcpy(dst, hdr->addr3, ETH_ALEN);
494 memcpy(src, hdr->addr4, ETH_ALEN);
495 break;
496 case 0:
497 memcpy(dst, hdr->addr1, ETH_ALEN);
498 memcpy(src, hdr->addr2, ETH_ALEN);
499 break;
500 }
501
502#ifdef NOT_YET
503 if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
504 goto rx_dropped;
505 if (wds) {
506 skb->dev = dev = wds;
507 stats = hostap_get_stats(dev);
508 }
509
510 if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
511 (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS &&
512 ieee->stadev &&
513 memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) {
514 /* Frame from BSSID of the AP for which we are a client */
515 skb->dev = dev = ieee->stadev;
516 stats = hostap_get_stats(dev);
517 from_assoc_ap = 1;
518 }
519#endif
520
521 dev->last_rx = jiffies;
522
523#ifdef NOT_YET
524 if ((ieee->iw_mode == IW_MODE_MASTER ||
525 ieee->iw_mode == IW_MODE_REPEAT) &&
526 !from_assoc_ap) {
527 switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
528 wds != NULL)) {
529 case AP_RX_CONTINUE_NOT_AUTHORIZED:
530 frame_authorized = 0;
531 break;
532 case AP_RX_CONTINUE:
533 frame_authorized = 1;
534 break;
535 case AP_RX_DROP:
536 goto rx_dropped;
537 case AP_RX_EXIT:
538 goto rx_exit;
539 }
540 }
541#endif
542
543 /* Nullfunc frames may have PS-bit set, so they must be passed to
544 * hostap_handle_sta_rx() before being dropped here. */
545 if (stype != IEEE80211_STYPE_DATA &&
546 stype != IEEE80211_STYPE_DATA_CFACK &&
547 stype != IEEE80211_STYPE_DATA_CFPOLL &&
548 stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
549 if (stype != IEEE80211_STYPE_NULLFUNC)
550 IEEE80211_DEBUG_DROP(
551 "RX: dropped data frame "
552 "with no data (type=0x%02x, "
553 "subtype=0x%02x, len=%d)\n",
554 type, stype, skb->len);
555 goto rx_dropped;
556 }
557
558 /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
559
560 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
561 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
562 goto rx_dropped;
563
564 hdr = (struct ieee80211_hdr *) skb->data;
565
566 /* skb: hdr + (possibly fragmented) plaintext payload */
567 // PR: FIXME: hostap has additional conditions in the "if" below:
568 // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
569 if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
570 int flen;
571 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
572 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
573
574 if (!frag_skb) {
575 IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
576 "Rx cannot get skb from fragment "
577 "cache (morefrag=%d seq=%u frag=%u)\n",
578 (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
579 WLAN_GET_SEQ_SEQ(sc), frag);
580 goto rx_dropped;
581 }
582
583 flen = skb->len;
584 if (frag != 0)
585 flen -= hdrlen;
586
587 if (frag_skb->tail + flen > frag_skb->end) {
588 printk(KERN_WARNING "%s: host decrypted and "
589 "reassembled frame did not fit skb\n",
590 dev->name);
591 ieee80211_frag_cache_invalidate(ieee, hdr);
592 goto rx_dropped;
593 }
594
595 if (frag == 0) {
596 /* copy first fragment (including full headers) into
597 * beginning of the fragment cache skb */
598 memcpy(skb_put(frag_skb, flen), skb->data, flen);
599 } else {
600 /* append frame payload to the end of the fragment
601 * cache skb */
602 memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
603 flen);
604 }
605 dev_kfree_skb_any(skb);
606 skb = NULL;
607
608 if (fc & IEEE80211_FCTL_MOREFRAGS) {
609 /* more fragments expected - leave the skb in fragment
610 * cache for now; it will be delivered to upper layers
611 * after all fragments have been received */
612 goto rx_exit;
613 }
614
615 /* this was the last fragment and the frame will be
616 * delivered, so remove skb from fragment cache */
617 skb = frag_skb;
618 hdr = (struct ieee80211_hdr *) skb->data;
619 ieee80211_frag_cache_invalidate(ieee, hdr);
620 }
621
622 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
623 * encrypted/authenticated */
624 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
625 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
626 goto rx_dropped;
627
628 hdr = (struct ieee80211_hdr *) skb->data;
629 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
630 if (/*ieee->ieee802_1x &&*/
631 ieee80211_is_eapol_frame(ieee, skb)) {
632#ifdef CONFIG_IEEE80211_DEBUG
633 /* pass unencrypted EAPOL frames even if encryption is
634 * configured */
635 struct eapol *eap = (struct eapol *)(skb->data +
636 24);
637 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
638 eap_get_type(eap->type));
639#endif
640 } else {
641 IEEE80211_DEBUG_DROP(
642 "encryption configured, but RX "
643 "frame not encrypted (SA=" MAC_FMT ")\n",
644 MAC_ARG(hdr->addr2));
645 goto rx_dropped;
646 }
647 }
648
649#ifdef CONFIG_IEEE80211_DEBUG
650 if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
651 ieee80211_is_eapol_frame(ieee, skb)) {
652 struct eapol *eap = (struct eapol *)(skb->data +
653 24);
654 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
655 eap_get_type(eap->type));
656 }
657#endif
658
659 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
660 !ieee80211_is_eapol_frame(ieee, skb)) {
661 IEEE80211_DEBUG_DROP(
662 "dropped unencrypted RX data "
663 "frame from " MAC_FMT
664 " (drop_unencrypted=1)\n",
665 MAC_ARG(hdr->addr2));
666 goto rx_dropped;
667 }
668
669 /* skb: hdr + (possible reassembled) full plaintext payload */
670
671 payload = skb->data + hdrlen;
672 ethertype = (payload[6] << 8) | payload[7];
673
674#ifdef NOT_YET
675 /* If IEEE 802.1X is used, check whether the port is authorized to send
676 * the received frame. */
677 if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) {
678 if (ethertype == ETH_P_PAE) {
679 printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n",
680 dev->name);
681 if (ieee->hostapd && ieee->apdev) {
682 /* Send IEEE 802.1X frames to the user
683 * space daemon for processing */
684 prism2_rx_80211(ieee->apdev, skb, rx_stats,
685 PRISM2_RX_MGMT);
686 ieee->apdevstats.rx_packets++;
687 ieee->apdevstats.rx_bytes += skb->len;
688 goto rx_exit;
689 }
690 } else if (!frame_authorized) {
691 printk(KERN_DEBUG "%s: dropped frame from "
692 "unauthorized port (IEEE 802.1X): "
693 "ethertype=0x%04x\n",
694 dev->name, ethertype);
695 goto rx_dropped;
696 }
697 }
698#endif
699
700 /* convert hdr + possible LLC headers into Ethernet header */
701 if (skb->len - hdrlen >= 8 &&
702 ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
703 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
704 memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
705 /* remove RFC1042 or Bridge-Tunnel encapsulation and
706 * replace EtherType */
707 skb_pull(skb, hdrlen + SNAP_SIZE);
708 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
709 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
710 } else {
711 u16 len;
712 /* Leave Ethernet header part of hdr and full payload */
713 skb_pull(skb, hdrlen);
714 len = htons(skb->len);
715 memcpy(skb_push(skb, 2), &len, 2);
716 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
717 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
718 }
719
720#ifdef NOT_YET
721 if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
722 IEEE80211_FCTL_TODS) &&
723 skb->len >= ETH_HLEN + ETH_ALEN) {
724 /* Non-standard frame: get addr4 from its bogus location after
725 * the payload */
726 memcpy(skb->data + ETH_ALEN,
727 skb->data + skb->len - ETH_ALEN, ETH_ALEN);
728 skb_trim(skb, skb->len - ETH_ALEN);
729 }
730#endif
731
732 stats->rx_packets++;
733 stats->rx_bytes += skb->len;
734
735#ifdef NOT_YET
736 if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
737 ieee->ap->bridge_packets) {
738 if (dst[0] & 0x01) {
739 /* copy multicast frame both to the higher layers and
740 * to the wireless media */
741 ieee->ap->bridged_multicast++;
742 skb2 = skb_clone(skb, GFP_ATOMIC);
743 if (skb2 == NULL)
744 printk(KERN_DEBUG "%s: skb_clone failed for "
745 "multicast frame\n", dev->name);
746 } else if (hostap_is_sta_assoc(ieee->ap, dst)) {
747 /* send frame directly to the associated STA using
748 * wireless media and not passing to higher layers */
749 ieee->ap->bridged_unicast++;
750 skb2 = skb;
751 skb = NULL;
752 }
753 }
754
755 if (skb2 != NULL) {
756 /* send to wireless media */
757 skb2->protocol = __constant_htons(ETH_P_802_3);
758 skb2->mac.raw = skb2->nh.raw = skb2->data;
759 /* skb2->nh.raw = skb2->data + ETH_HLEN; */
760 skb2->dev = dev;
761 dev_queue_xmit(skb2);
762 }
763
764#endif
765
766 if (skb) {
767 skb->protocol = eth_type_trans(skb, dev);
768 memset(skb->cb, 0, sizeof(skb->cb));
769 skb->dev = dev;
770 skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
771 netif_rx(skb);
772 }
773
774 rx_exit:
775#ifdef NOT_YET
776 if (sta)
777 hostap_handle_sta_release(sta);
778#endif
779 return 1;
780
781 rx_dropped:
782 stats->rx_dropped++;
783
784 /* Returning 0 indicates to caller that we have not handled the SKB--
785 * so it is still allocated and can be used again by underlying
786 * hardware as a DMA target */
787 return 0;
788}
789
790#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
791
792static inline int ieee80211_is_ofdm_rate(u8 rate)
793{
794 switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
795 case IEEE80211_OFDM_RATE_6MB:
796 case IEEE80211_OFDM_RATE_9MB:
797 case IEEE80211_OFDM_RATE_12MB:
798 case IEEE80211_OFDM_RATE_18MB:
799 case IEEE80211_OFDM_RATE_24MB:
800 case IEEE80211_OFDM_RATE_36MB:
801 case IEEE80211_OFDM_RATE_48MB:
802 case IEEE80211_OFDM_RATE_54MB:
803 return 1;
804 }
805 return 0;
806}
807
808
809static inline int ieee80211_network_init(
810 struct ieee80211_device *ieee,
811 struct ieee80211_probe_response *beacon,
812 struct ieee80211_network *network,
813 struct ieee80211_rx_stats *stats)
814{
815#ifdef CONFIG_IEEE80211_DEBUG
816 char rates_str[64];
817 char *p;
818#endif
819 struct ieee80211_info_element *info_element;
820 u16 left;
821 u8 i;
822
823 /* Pull out fixed field data */
824 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
825 network->capability = beacon->capability;
826 network->last_scanned = jiffies;
827 network->time_stamp[0] = beacon->time_stamp[0];
828 network->time_stamp[1] = beacon->time_stamp[1];
829 network->beacon_interval = beacon->beacon_interval;
830 /* Where to pull this? beacon->listen_interval;*/
831 network->listen_interval = 0x0A;
832 network->rates_len = network->rates_ex_len = 0;
833 network->last_associate = 0;
834 network->ssid_len = 0;
835 network->flags = 0;
836 network->atim_window = 0;
837
838 if (stats->freq == IEEE80211_52GHZ_BAND) {
839 /* for A band (No DS info) */
840 network->channel = stats->received_channel;
841 } else
842 network->flags |= NETWORK_HAS_CCK;
843
844 network->wpa_ie_len = 0;
845 network->rsn_ie_len = 0;
846
847 info_element = &beacon->info_element;
848 left = stats->len - ((void *)info_element - (void *)beacon);
849 while (left >= sizeof(struct ieee80211_info_element_hdr)) {
850 if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
851 IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
852 info_element->len + sizeof(struct ieee80211_info_element),
853 left);
854 return 1;
855 }
856
857 switch (info_element->id) {
858 case MFIE_TYPE_SSID:
859 if (ieee80211_is_empty_essid(info_element->data,
860 info_element->len)) {
861 network->flags |= NETWORK_EMPTY_ESSID;
862 break;
863 }
864
865 network->ssid_len = min(info_element->len,
866 (u8)IW_ESSID_MAX_SIZE);
867 memcpy(network->ssid, info_element->data, network->ssid_len);
868 if (network->ssid_len < IW_ESSID_MAX_SIZE)
869 memset(network->ssid + network->ssid_len, 0,
870 IW_ESSID_MAX_SIZE - network->ssid_len);
871
872 IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
873 network->ssid, network->ssid_len);
874 break;
875
876 case MFIE_TYPE_RATES:
877#ifdef CONFIG_IEEE80211_DEBUG
878 p = rates_str;
879#endif
880 network->rates_len = min(info_element->len, MAX_RATES_LENGTH);
881 for (i = 0; i < network->rates_len; i++) {
882 network->rates[i] = info_element->data[i];
883#ifdef CONFIG_IEEE80211_DEBUG
884 p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
885#endif
886 if (ieee80211_is_ofdm_rate(info_element->data[i])) {
887 network->flags |= NETWORK_HAS_OFDM;
888 if (info_element->data[i] &
889 IEEE80211_BASIC_RATE_MASK)
890 network->flags &=
891 ~NETWORK_HAS_CCK;
892 }
893 }
894
895 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
896 rates_str, network->rates_len);
897 break;
898
899 case MFIE_TYPE_RATES_EX:
900#ifdef CONFIG_IEEE80211_DEBUG
901 p = rates_str;
902#endif
903 network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH);
904 for (i = 0; i < network->rates_ex_len; i++) {
905 network->rates_ex[i] = info_element->data[i];
906#ifdef CONFIG_IEEE80211_DEBUG
907 p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
908#endif
909 if (ieee80211_is_ofdm_rate(info_element->data[i])) {
910 network->flags |= NETWORK_HAS_OFDM;
911 if (info_element->data[i] &
912 IEEE80211_BASIC_RATE_MASK)
913 network->flags &=
914 ~NETWORK_HAS_CCK;
915 }
916 }
917
918 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
919 rates_str, network->rates_ex_len);
920 break;
921
922 case MFIE_TYPE_DS_SET:
923 IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
924 info_element->data[0]);
925 if (stats->freq == IEEE80211_24GHZ_BAND)
926 network->channel = info_element->data[0];
927 break;
928
929 case MFIE_TYPE_FH_SET:
930 IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
931 break;
932
933 case MFIE_TYPE_CF_SET:
934 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
935 break;
936
937 case MFIE_TYPE_TIM:
938 IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
939 break;
940
941 case MFIE_TYPE_IBSS_SET:
942 IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
943 break;
944
945 case MFIE_TYPE_CHALLENGE:
946 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
947 break;
948
949 case MFIE_TYPE_GENERIC:
950 IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
951 info_element->len);
952 if (info_element->len >= 4 &&
953 info_element->data[0] == 0x00 &&
954 info_element->data[1] == 0x50 &&
955 info_element->data[2] == 0xf2 &&
956 info_element->data[3] == 0x01) {
957 network->wpa_ie_len = min(info_element->len + 2,
958 MAX_WPA_IE_LEN);
959 memcpy(network->wpa_ie, info_element,
960 network->wpa_ie_len);
961 }
962 break;
963
964 case MFIE_TYPE_RSN:
965 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
966 info_element->len);
967 network->rsn_ie_len = min(info_element->len + 2,
968 MAX_WPA_IE_LEN);
969 memcpy(network->rsn_ie, info_element,
970 network->rsn_ie_len);
971 break;
972
973 default:
974 IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
975 info_element->id);
976 break;
977 }
978
979 left -= sizeof(struct ieee80211_info_element_hdr) +
980 info_element->len;
981 info_element = (struct ieee80211_info_element *)
982 &info_element->data[info_element->len];
983 }
984
985 network->mode = 0;
986 if (stats->freq == IEEE80211_52GHZ_BAND)
987 network->mode = IEEE_A;
988 else {
989 if (network->flags & NETWORK_HAS_OFDM)
990 network->mode |= IEEE_G;
991 if (network->flags & NETWORK_HAS_CCK)
992 network->mode |= IEEE_B;
993 }
994
995 if (network->mode == 0) {
996 IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
997 "network.\n",
998 escape_essid(network->ssid,
999 network->ssid_len),
1000 MAC_ARG(network->bssid));
1001 return 1;
1002 }
1003
1004 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1005 network->flags |= NETWORK_EMPTY_ESSID;
1006
1007 memcpy(&network->stats, stats, sizeof(network->stats));
1008
1009 return 0;
1010}
1011
1012static inline int is_same_network(struct ieee80211_network *src,
1013 struct ieee80211_network *dst)
1014{
1015 /* A network is only a duplicate if the channel, BSSID, and ESSID
1016 * all match. We treat all <hidden> with the same BSSID and channel
1017 * as one network */
1018 return ((src->ssid_len == dst->ssid_len) &&
1019 (src->channel == dst->channel) &&
1020 !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
1021 !memcmp(src->ssid, dst->ssid, src->ssid_len));
1022}
1023
1024static inline void update_network(struct ieee80211_network *dst,
1025 struct ieee80211_network *src)
1026{
1027 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1028 dst->capability = src->capability;
1029 memcpy(dst->rates, src->rates, src->rates_len);
1030 dst->rates_len = src->rates_len;
1031 memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
1032 dst->rates_ex_len = src->rates_ex_len;
1033
1034 dst->mode = src->mode;
1035 dst->flags = src->flags;
1036 dst->time_stamp[0] = src->time_stamp[0];
1037 dst->time_stamp[1] = src->time_stamp[1];
1038
1039 dst->beacon_interval = src->beacon_interval;
1040 dst->listen_interval = src->listen_interval;
1041 dst->atim_window = src->atim_window;
1042
1043 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1044 dst->wpa_ie_len = src->wpa_ie_len;
1045 memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
1046 dst->rsn_ie_len = src->rsn_ie_len;
1047
1048 dst->last_scanned = jiffies;
1049 /* dst->last_associate is not overwritten */
1050}
1051
1052static inline void ieee80211_process_probe_response(
1053 struct ieee80211_device *ieee,
1054 struct ieee80211_probe_response *beacon,
1055 struct ieee80211_rx_stats *stats)
1056{
1057 struct ieee80211_network network;
1058 struct ieee80211_network *target;
1059 struct ieee80211_network *oldest = NULL;
1060#ifdef CONFIG_IEEE80211_DEBUG
1061 struct ieee80211_info_element *info_element = &beacon->info_element;
1062#endif
1063 unsigned long flags;
1064
1065 IEEE80211_DEBUG_SCAN(
1066 "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
1067 escape_essid(info_element->data, info_element->len),
1068 MAC_ARG(beacon->header.addr3),
1069 (beacon->capability & (1<<0xf)) ? '1' : '0',
1070 (beacon->capability & (1<<0xe)) ? '1' : '0',
1071 (beacon->capability & (1<<0xd)) ? '1' : '0',
1072 (beacon->capability & (1<<0xc)) ? '1' : '0',
1073 (beacon->capability & (1<<0xb)) ? '1' : '0',
1074 (beacon->capability & (1<<0xa)) ? '1' : '0',
1075 (beacon->capability & (1<<0x9)) ? '1' : '0',
1076 (beacon->capability & (1<<0x8)) ? '1' : '0',
1077 (beacon->capability & (1<<0x7)) ? '1' : '0',
1078 (beacon->capability & (1<<0x6)) ? '1' : '0',
1079 (beacon->capability & (1<<0x5)) ? '1' : '0',
1080 (beacon->capability & (1<<0x4)) ? '1' : '0',
1081 (beacon->capability & (1<<0x3)) ? '1' : '0',
1082 (beacon->capability & (1<<0x2)) ? '1' : '0',
1083 (beacon->capability & (1<<0x1)) ? '1' : '0',
1084 (beacon->capability & (1<<0x0)) ? '1' : '0');
1085
1086 if (ieee80211_network_init(ieee, beacon, &network, stats)) {
1087 IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
1088 escape_essid(info_element->data,
1089 info_element->len),
1090 MAC_ARG(beacon->header.addr3),
1091 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1092 IEEE80211_STYPE_PROBE_RESP ?
1093 "PROBE RESPONSE" : "BEACON");
1094 return;
1095 }
1096
1097 /* The network parsed correctly -- so now we scan our known networks
1098 * to see if we can find it in our list.
1099 *
1100 * NOTE: This search is definitely not optimized. Once its doing
1101 * the "right thing" we'll optimize it for efficiency if
1102 * necessary */
1103
1104 /* Search for this entry in the list and update it if it is
1105 * already there. */
1106
1107 spin_lock_irqsave(&ieee->lock, flags);
1108
1109 list_for_each_entry(target, &ieee->network_list, list) {
1110 if (is_same_network(target, &network))
1111 break;
1112
1113 if ((oldest == NULL) ||
1114 (target->last_scanned < oldest->last_scanned))
1115 oldest = target;
1116 }
1117
1118 /* If we didn't find a match, then get a new network slot to initialize
1119 * with this beacon's information */
1120 if (&target->list == &ieee->network_list) {
1121 if (list_empty(&ieee->network_free_list)) {
1122 /* If there are no more slots, expire the oldest */
1123 list_del(&oldest->list);
1124 target = oldest;
1125 IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
1126 "network list.\n",
1127 escape_essid(target->ssid,
1128 target->ssid_len),
1129 MAC_ARG(target->bssid));
1130 } else {
1131 /* Otherwise just pull from the free list */
1132 target = list_entry(ieee->network_free_list.next,
1133 struct ieee80211_network, list);
1134 list_del(ieee->network_free_list.next);
1135 }
1136
1137
1138#ifdef CONFIG_IEEE80211_DEBUG
1139 IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
1140 escape_essid(network.ssid,
1141 network.ssid_len),
1142 MAC_ARG(network.bssid),
1143 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1144 IEEE80211_STYPE_PROBE_RESP ?
1145 "PROBE RESPONSE" : "BEACON");
1146#endif
1147 memcpy(target, &network, sizeof(*target));
1148 list_add_tail(&target->list, &ieee->network_list);
1149 } else {
1150 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
1151 escape_essid(target->ssid,
1152 target->ssid_len),
1153 MAC_ARG(target->bssid),
1154 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1155 IEEE80211_STYPE_PROBE_RESP ?
1156 "PROBE RESPONSE" : "BEACON");
1157 update_network(target, &network);
1158 }
1159
1160 spin_unlock_irqrestore(&ieee->lock, flags);
1161}
1162
1163void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1164 struct ieee80211_hdr *header,
1165 struct ieee80211_rx_stats *stats)
1166{
1167 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1168 case IEEE80211_STYPE_ASSOC_RESP:
1169 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
1170 WLAN_FC_GET_STYPE(header->frame_ctl));
1171 break;
1172
1173 case IEEE80211_STYPE_REASSOC_RESP:
1174 IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
1175 WLAN_FC_GET_STYPE(header->frame_ctl));
1176 break;
1177
1178 case IEEE80211_STYPE_PROBE_RESP:
1179 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1180 WLAN_FC_GET_STYPE(header->frame_ctl));
1181 IEEE80211_DEBUG_SCAN("Probe response\n");
1182 ieee80211_process_probe_response(
1183 ieee, (struct ieee80211_probe_response *)header, stats);
1184 break;
1185
1186 case IEEE80211_STYPE_BEACON:
1187 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1188 WLAN_FC_GET_STYPE(header->frame_ctl));
1189 IEEE80211_DEBUG_SCAN("Beacon\n");
1190 ieee80211_process_probe_response(
1191 ieee, (struct ieee80211_probe_response *)header, stats);
1192 break;
1193
1194 default:
1195 IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
1196 WLAN_FC_GET_STYPE(header->frame_ctl));
1197 IEEE80211_WARNING("%s: Unknown management packet: %d\n",
1198 ieee->dev->name,
1199 WLAN_FC_GET_STYPE(header->frame_ctl));
1200 break;
1201 }
1202}
1203
1204
1205EXPORT_SYMBOL(ieee80211_rx_mgt);
1206EXPORT_SYMBOL(ieee80211_rx);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
new file mode 100644
index 000000000000..d70e6b82715e
--- /dev/null
+++ b/net/ieee80211/ieee80211_tx.c
@@ -0,0 +1,448 @@
1/******************************************************************************
2
3 Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Contact Information:
22 James P. Ketrenos <ipw2100-admin@linux.intel.com>
23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25******************************************************************************/
26#include <linux/compiler.h>
27#include <linux/config.h>
28#include <linux/errno.h>
29#include <linux/if_arp.h>
30#include <linux/in6.h>
31#include <linux/in.h>
32#include <linux/ip.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/netdevice.h>
36#include <linux/pci.h>
37#include <linux/proc_fs.h>
38#include <linux/skbuff.h>
39#include <linux/slab.h>
40#include <linux/tcp.h>
41#include <linux/types.h>
42#include <linux/version.h>
43#include <linux/wireless.h>
44#include <linux/etherdevice.h>
45#include <asm/uaccess.h>
46
47#include <net/ieee80211.h>
48
49
50/*
51
52
53802.11 Data Frame
54
55 ,-------------------------------------------------------------------.
56Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
57 |------|------|---------|---------|---------|------|---------|------|
58Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
59 | | tion | (BSSID) | | | ence | data | |
60 `--------------------------------------------------| |------'
61Total: 28 non-data bytes `----.----'
62 |
63 .- 'Frame data' expands to <---------------------------'
64 |
65 V
66 ,---------------------------------------------------.
67Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
68 |------|------|---------|----------|------|---------|
69Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
70 | DSAP | SSAP | | | | Packet |
71 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
72 `-----------------------------------------| |
73Total: 8 non-data bytes `----.----'
74 |
75 .- 'IP Packet' expands, if WEP enabled, to <--'
76 |
77 V
78 ,-----------------------.
79Bytes | 4 | 0-2296 | 4 |
80 |-----|-----------|-----|
81Desc. | IV | Encrypted | ICV |
82 | | IP Packet | |
83 `-----------------------'
84Total: 8 non-data bytes
85
86
87802.3 Ethernet Data Frame
88
89 ,-----------------------------------------.
90Bytes | 6 | 6 | 2 | Variable | 4 |
91 |-------|-------|------|-----------|------|
92Desc. | Dest. | Source| Type | IP Packet | fcs |
93 | MAC | MAC | | | |
94 `-----------------------------------------'
95Total: 18 non-data bytes
96
97In the event that fragmentation is required, the incoming payload is split into
98N parts of size ieee->fts. The first fragment contains the SNAP header and the
99remaining packets are just data.
100
101If encryption is enabled, each fragment payload size is reduced by enough space
102to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
103So if you have 1500 bytes of payload with ieee->fts set to 500 without
104encryption it will take 3 frames. With WEP it will take 4 frames as the
105payload of each frame is reduced to 492 bytes.
106
107* SKB visualization
108*
109* ,- skb->data
110* |
111* | ETHERNET HEADER ,-<-- PAYLOAD
112* | | 14 bytes from skb->data
113* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
114* | | | |
115* |,-Dest.--. ,--Src.---. | | |
116* | 6 bytes| | 6 bytes | | | |
117* v | | | | | |
118* 0 | v 1 | v | v 2
119* 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
120* ^ | ^ | ^ |
121* | | | | | |
122* | | | | `T' <---- 2 bytes for Type
123* | | | |
124* | | '---SNAP--' <-------- 6 bytes for SNAP
125* | |
126* `-IV--' <-------------------- 4 bytes for IV (WEP)
127*
128* SNAP HEADER
129*
130*/
131
132static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
133static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
134
135static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
136{
137 struct ieee80211_snap_hdr *snap;
138 u8 *oui;
139
140 snap = (struct ieee80211_snap_hdr *)data;
141 snap->dsap = 0xaa;
142 snap->ssap = 0xaa;
143 snap->ctrl = 0x03;
144
145 if (h_proto == 0x8137 || h_proto == 0x80f3)
146 oui = P802_1H_OUI;
147 else
148 oui = RFC1042_OUI;
149 snap->oui[0] = oui[0];
150 snap->oui[1] = oui[1];
151 snap->oui[2] = oui[2];
152
153 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
154
155 return SNAP_SIZE + sizeof(u16);
156}
157
158static inline int ieee80211_encrypt_fragment(
159 struct ieee80211_device *ieee,
160 struct sk_buff *frag,
161 int hdr_len)
162{
163 struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
164 int res;
165
166#ifdef CONFIG_IEEE80211_CRYPT_TKIP
167 struct ieee80211_hdr *header;
168
169 if (ieee->tkip_countermeasures &&
170 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
171 header = (struct ieee80211_hdr *) frag->data;
172 if (net_ratelimit()) {
173 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
174 "TX packet to " MAC_FMT "\n",
175 ieee->dev->name, MAC_ARG(header->addr1));
176 }
177 return -1;
178 }
179#endif
180 /* To encrypt, frame format is:
181 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
182
183 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
184 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
185 * call both MSDU and MPDU encryption functions from here. */
186 atomic_inc(&crypt->refcnt);
187 res = 0;
188 if (crypt->ops->encrypt_msdu)
189 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
190 if (res == 0 && crypt->ops->encrypt_mpdu)
191 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
192
193 atomic_dec(&crypt->refcnt);
194 if (res < 0) {
195 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
196 ieee->dev->name, frag->len);
197 ieee->ieee_stats.tx_discards++;
198 return -1;
199 }
200
201 return 0;
202}
203
204
205void ieee80211_txb_free(struct ieee80211_txb *txb) {
206 int i;
207 if (unlikely(!txb))
208 return;
209 for (i = 0; i < txb->nr_frags; i++)
210 if (txb->fragments[i])
211 dev_kfree_skb_any(txb->fragments[i]);
212 kfree(txb);
213}
214
215struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
216 int gfp_mask)
217{
218 struct ieee80211_txb *txb;
219 int i;
220 txb = kmalloc(
221 sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
222 gfp_mask);
223 if (!txb)
224 return NULL;
225
226 memset(txb, sizeof(struct ieee80211_txb), 0);
227 txb->nr_frags = nr_frags;
228 txb->frag_size = txb_size;
229
230 for (i = 0; i < nr_frags; i++) {
231 txb->fragments[i] = dev_alloc_skb(txb_size);
232 if (unlikely(!txb->fragments[i])) {
233 i--;
234 break;
235 }
236 }
237 if (unlikely(i != nr_frags)) {
238 while (i >= 0)
239 dev_kfree_skb_any(txb->fragments[i--]);
240 kfree(txb);
241 return NULL;
242 }
243 return txb;
244}
245
246/* SKBs are added to the ieee->tx_queue. */
247int ieee80211_xmit(struct sk_buff *skb,
248 struct net_device *dev)
249{
250 struct ieee80211_device *ieee = netdev_priv(dev);
251 struct ieee80211_txb *txb = NULL;
252 struct ieee80211_hdr *frag_hdr;
253 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
254 unsigned long flags;
255 struct net_device_stats *stats = &ieee->stats;
256 int ether_type, encrypt;
257 int bytes, fc, hdr_len;
258 struct sk_buff *skb_frag;
259 struct ieee80211_hdr header = { /* Ensure zero initialized */
260 .duration_id = 0,
261 .seq_ctl = 0
262 };
263 u8 dest[ETH_ALEN], src[ETH_ALEN];
264
265 struct ieee80211_crypt_data* crypt;
266
267 spin_lock_irqsave(&ieee->lock, flags);
268
269 /* If there is no driver handler to take the TXB, dont' bother
270 * creating it... */
271 if (!ieee->hard_start_xmit) {
272 printk(KERN_WARNING "%s: No xmit handler.\n",
273 ieee->dev->name);
274 goto success;
275 }
276
277 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
278 printk(KERN_WARNING "%s: skb too small (%d).\n",
279 ieee->dev->name, skb->len);
280 goto success;
281 }
282
283 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
284
285 crypt = ieee->crypt[ieee->tx_keyidx];
286
287 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
288 ieee->host_encrypt && crypt && crypt->ops;
289
290 if (!encrypt && ieee->ieee802_1x &&
291 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
292 stats->tx_dropped++;
293 goto success;
294 }
295
296#ifdef CONFIG_IEEE80211_DEBUG
297 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
298 struct eapol *eap = (struct eapol *)(skb->data +
299 sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
300 IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
301 eap_get_type(eap->type));
302 }
303#endif
304
305 /* Save source and destination addresses */
306 memcpy(&dest, skb->data, ETH_ALEN);
307 memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
308
309 /* Advance the SKB to the start of the payload */
310 skb_pull(skb, sizeof(struct ethhdr));
311
312 /* Determine total amount of storage required for TXB packets */
313 bytes = skb->len + SNAP_SIZE + sizeof(u16);
314
315 if (encrypt)
316 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
317 IEEE80211_FCTL_WEP;
318 else
319 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
320
321 if (ieee->iw_mode == IW_MODE_INFRA) {
322 fc |= IEEE80211_FCTL_TODS;
323 /* To DS: Addr1 = BSSID, Addr2 = SA,
324 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,
330 Addr3 = BSSID */
331 memcpy(&header.addr1, dest, ETH_ALEN);
332 memcpy(&header.addr2, src, ETH_ALEN);
333 memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
334 }
335 header.frame_ctl = cpu_to_le16(fc);
336 hdr_len = IEEE80211_3ADDR_LEN;
337
338 /* Determine fragmentation size based on destination (multicast
339 * and broadcast are not fragmented) */
340 if (is_multicast_ether_addr(dest) ||
341 is_broadcast_ether_addr(dest))
342 frag_size = MAX_FRAG_THRESHOLD;
343 else
344 frag_size = ieee->fts;
345
346 /* Determine amount of payload per fragment. Regardless of if
347 * this stack is providing the full 802.11 header, one will
348 * eventually be affixed to this fragment -- so we must account for
349 * it when determining the amount of payload space. */
350 bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
351 if (ieee->config &
352 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
353 bytes_per_frag -= IEEE80211_FCS_LEN;
354
355 /* Each fragment may need to have room for encryptiong pre/postfix */
356 if (encrypt)
357 bytes_per_frag -= crypt->ops->extra_prefix_len +
358 crypt->ops->extra_postfix_len;
359
360 /* Number of fragments is the total bytes_per_frag /
361 * payload_per_fragment */
362 nr_frags = bytes / bytes_per_frag;
363 bytes_last_frag = bytes % bytes_per_frag;
364 if (bytes_last_frag)
365 nr_frags++;
366 else
367 bytes_last_frag = bytes_per_frag;
368
369 /* When we allocate the TXB we allocate enough space for the reserve
370 * and full fragment bytes (bytes_per_frag doesn't include prefix,
371 * postfix, header, FCS, etc.) */
372 txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
373 if (unlikely(!txb)) {
374 printk(KERN_WARNING "%s: Could not allocate TXB\n",
375 ieee->dev->name);
376 goto failed;
377 }
378 txb->encrypted = encrypt;
379 txb->payload_size = bytes;
380
381 for (i = 0; i < nr_frags; i++) {
382 skb_frag = txb->fragments[i];
383
384 if (encrypt)
385 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
386
387 frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
388 memcpy(frag_hdr, &header, hdr_len);
389
390 /* If this is not the last fragment, then add the MOREFRAGS
391 * bit to the frame control */
392 if (i != nr_frags - 1) {
393 frag_hdr->frame_ctl = cpu_to_le16(
394 fc | IEEE80211_FCTL_MOREFRAGS);
395 bytes = bytes_per_frag;
396 } else {
397 /* The last fragment takes the remaining length */
398 bytes = bytes_last_frag;
399 }
400
401 /* Put a SNAP header on the first fragment */
402 if (i == 0) {
403 ieee80211_put_snap(
404 skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
405 ether_type);
406 bytes -= SNAP_SIZE + sizeof(u16);
407 }
408
409 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
410
411 /* Advance the SKB... */
412 skb_pull(skb, bytes);
413
414 /* Encryption routine will move the header forward in order
415 * to insert the IV between the header and the payload */
416 if (encrypt)
417 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
418 if (ieee->config &
419 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
420 skb_put(skb_frag, 4);
421 }
422
423
424 success:
425 spin_unlock_irqrestore(&ieee->lock, flags);
426
427 dev_kfree_skb_any(skb);
428
429 if (txb) {
430 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
431 stats->tx_packets++;
432 stats->tx_bytes += txb->payload_size;
433 return 0;
434 }
435 ieee80211_txb_free(txb);
436 }
437
438 return 0;
439
440 failed:
441 spin_unlock_irqrestore(&ieee->lock, flags);
442 netif_stop_queue(dev);
443 stats->tx_errors++;
444 return 1;
445
446}
447
448EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
new file mode 100644
index 000000000000..25a868c2e2f7
--- /dev/null
+++ b/net/ieee80211/ieee80211_wx.c
@@ -0,0 +1,471 @@
1/******************************************************************************
2
3 Copyright(c) 2004 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 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.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#include <linux/wireless.h>
33#include <linux/version.h>
34#include <linux/kmod.h>
35#include <linux/module.h>
36
37#include <net/ieee80211.h>
38static const char *ieee80211_modes[] = {
39 "?", "a", "b", "ab", "g", "ag", "bg", "abg"
40};
41
42#define MAX_CUSTOM_LEN 64
43static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
44 char *start, char *stop,
45 struct ieee80211_network *network)
46{
47 char custom[MAX_CUSTOM_LEN];
48 char *p;
49 struct iw_event iwe;
50 int i, j;
51 u8 max_rate, rate;
52
53 /* First entry *MUST* be the AP MAC address */
54 iwe.cmd = SIOCGIWAP;
55 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
56 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
57 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
58
59 /* Remaining entries will be displayed in the order we provide them */
60
61 /* Add the ESSID */
62 iwe.cmd = SIOCGIWESSID;
63 iwe.u.data.flags = 1;
64 if (network->flags & NETWORK_EMPTY_ESSID) {
65 iwe.u.data.length = sizeof("<hidden>");
66 start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
67 } else {
68 iwe.u.data.length = min(network->ssid_len, (u8)32);
69 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
70 }
71
72 /* Add the protocol name */
73 iwe.cmd = SIOCGIWNAME;
74 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
75 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN);
76
77 /* Add mode */
78 iwe.cmd = SIOCGIWMODE;
79 if (network->capability &
80 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
81 if (network->capability & WLAN_CAPABILITY_BSS)
82 iwe.u.mode = IW_MODE_MASTER;
83 else
84 iwe.u.mode = IW_MODE_ADHOC;
85
86 start = iwe_stream_add_event(start, stop, &iwe,
87 IW_EV_UINT_LEN);
88 }
89
90 /* Add frequency/channel */
91 iwe.cmd = SIOCGIWFREQ;
92/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
93 iwe.u.freq.e = 3; */
94 iwe.u.freq.m = network->channel;
95 iwe.u.freq.e = 0;
96 iwe.u.freq.i = 0;
97 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
98
99 /* Add encryption capability */
100 iwe.cmd = SIOCGIWENCODE;
101 if (network->capability & WLAN_CAPABILITY_PRIVACY)
102 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
103 else
104 iwe.u.data.flags = IW_ENCODE_DISABLED;
105 iwe.u.data.length = 0;
106 start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
107
108 /* Add basic and extended rates */
109 max_rate = 0;
110 p = custom;
111 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
112 for (i = 0, j = 0; i < network->rates_len; ) {
113 if (j < network->rates_ex_len &&
114 ((network->rates_ex[j] & 0x7F) <
115 (network->rates[i] & 0x7F)))
116 rate = network->rates_ex[j++] & 0x7F;
117 else
118 rate = network->rates[i++] & 0x7F;
119 if (rate > max_rate)
120 max_rate = rate;
121 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
122 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
123 }
124 for (; j < network->rates_ex_len; j++) {
125 rate = network->rates_ex[j] & 0x7F;
126 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
127 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
128 if (rate > max_rate)
129 max_rate = rate;
130 }
131
132 iwe.cmd = SIOCGIWRATE;
133 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
134 iwe.u.bitrate.value = max_rate * 500000;
135 start = iwe_stream_add_event(start, stop, &iwe,
136 IW_EV_PARAM_LEN);
137
138 iwe.cmd = IWEVCUSTOM;
139 iwe.u.data.length = p - custom;
140 if (iwe.u.data.length)
141 start = iwe_stream_add_point(start, stop, &iwe, custom);
142
143 /* Add quality statistics */
144 /* TODO: Fix these values... */
145 iwe.cmd = IWEVQUAL;
146 iwe.u.qual.qual = network->stats.signal;
147 iwe.u.qual.level = network->stats.rssi;
148 iwe.u.qual.noise = network->stats.noise;
149 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
150 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
151 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
152 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
153 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
154 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
155 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
156
157 start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
158
159 iwe.cmd = IWEVCUSTOM;
160 p = custom;
161
162 iwe.u.data.length = p - custom;
163 if (iwe.u.data.length)
164 start = iwe_stream_add_point(start, stop, &iwe, custom);
165
166 if (ieee->wpa_enabled && network->wpa_ie_len){
167 char buf[MAX_WPA_IE_LEN * 2 + 30];
168
169 u8 *p = buf;
170 p += sprintf(p, "wpa_ie=");
171 for (i = 0; i < network->wpa_ie_len; i++) {
172 p += sprintf(p, "%02x", network->wpa_ie[i]);
173 }
174
175 memset(&iwe, 0, sizeof(iwe));
176 iwe.cmd = IWEVCUSTOM;
177 iwe.u.data.length = strlen(buf);
178 start = iwe_stream_add_point(start, stop, &iwe, buf);
179 }
180
181 if (ieee->wpa_enabled && network->rsn_ie_len){
182 char buf[MAX_WPA_IE_LEN * 2 + 30];
183
184 u8 *p = buf;
185 p += sprintf(p, "rsn_ie=");
186 for (i = 0; i < network->rsn_ie_len; i++) {
187 p += sprintf(p, "%02x", network->rsn_ie[i]);
188 }
189
190 memset(&iwe, 0, sizeof(iwe));
191 iwe.cmd = IWEVCUSTOM;
192 iwe.u.data.length = strlen(buf);
193 start = iwe_stream_add_point(start, stop, &iwe, buf);
194 }
195
196 /* Add EXTRA: Age to display seconds since last beacon/probe response
197 * for given network. */
198 iwe.cmd = IWEVCUSTOM;
199 p = custom;
200 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
201 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
202 iwe.u.data.length = p - custom;
203 if (iwe.u.data.length)
204 start = iwe_stream_add_point(start, stop, &iwe, custom);
205
206
207 return start;
208}
209
210int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
211 struct iw_request_info *info,
212 union iwreq_data *wrqu, char *extra)
213{
214 struct ieee80211_network *network;
215 unsigned long flags;
216
217 char *ev = extra;
218 char *stop = ev + IW_SCAN_MAX_DATA;
219 int i = 0;
220
221 IEEE80211_DEBUG_WX("Getting scan\n");
222
223 spin_lock_irqsave(&ieee->lock, flags);
224
225 list_for_each_entry(network, &ieee->network_list, list) {
226 i++;
227 if (ieee->scan_age == 0 ||
228 time_after(network->last_scanned + ieee->scan_age, jiffies))
229 ev = ipw2100_translate_scan(ieee, ev, stop, network);
230 else
231 IEEE80211_DEBUG_SCAN(
232 "Not showing network '%s ("
233 MAC_FMT ")' due to age (%lums).\n",
234 escape_essid(network->ssid,
235 network->ssid_len),
236 MAC_ARG(network->bssid),
237 (jiffies - network->last_scanned) / (HZ / 100));
238 }
239
240 spin_unlock_irqrestore(&ieee->lock, flags);
241
242 wrqu->data.length = ev - extra;
243 wrqu->data.flags = 0;
244
245 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
246
247 return 0;
248}
249
250int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
251 struct iw_request_info *info,
252 union iwreq_data *wrqu, char *keybuf)
253{
254 struct iw_point *erq = &(wrqu->encoding);
255 struct net_device *dev = ieee->dev;
256 struct ieee80211_security sec = {
257 .flags = 0
258 };
259 int i, key, key_provided, len;
260 struct ieee80211_crypt_data **crypt;
261
262 IEEE80211_DEBUG_WX("SET_ENCODE\n");
263
264 key = erq->flags & IW_ENCODE_INDEX;
265 if (key) {
266 if (key > WEP_KEYS)
267 return -EINVAL;
268 key--;
269 key_provided = 1;
270 } else {
271 key_provided = 0;
272 key = ieee->tx_keyidx;
273 }
274
275 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
276 "provided" : "default");
277
278 crypt = &ieee->crypt[key];
279
280 if (erq->flags & IW_ENCODE_DISABLED) {
281 if (key_provided && *crypt) {
282 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
283 key);
284 ieee80211_crypt_delayed_deinit(ieee, crypt);
285 } else
286 IEEE80211_DEBUG_WX("Disabling encryption.\n");
287
288 /* Check all the keys to see if any are still configured,
289 * and if no key index was provided, de-init them all */
290 for (i = 0; i < WEP_KEYS; i++) {
291 if (ieee->crypt[i] != NULL) {
292 if (key_provided)
293 break;
294 ieee80211_crypt_delayed_deinit(
295 ieee, &ieee->crypt[i]);
296 }
297 }
298
299 if (i == WEP_KEYS) {
300 sec.enabled = 0;
301 sec.level = SEC_LEVEL_0;
302 sec.flags |= SEC_ENABLED | SEC_LEVEL;
303 }
304
305 goto done;
306 }
307
308
309
310 sec.enabled = 1;
311 sec.flags |= SEC_ENABLED;
312
313 if (*crypt != NULL && (*crypt)->ops != NULL &&
314 strcmp((*crypt)->ops->name, "WEP") != 0) {
315 /* changing to use WEP; deinit previously used algorithm
316 * on this key */
317 ieee80211_crypt_delayed_deinit(ieee, crypt);
318 }
319
320 if (*crypt == NULL) {
321 struct ieee80211_crypt_data *new_crypt;
322
323 /* take WEP into use */
324 new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
325 GFP_KERNEL);
326 if (new_crypt == NULL)
327 return -ENOMEM;
328 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
329 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
330 if (!new_crypt->ops) {
331 request_module("ieee80211_crypt_wep");
332 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
333 }
334
335 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
336 new_crypt->priv = new_crypt->ops->init(key);
337
338 if (!new_crypt->ops || !new_crypt->priv) {
339 kfree(new_crypt);
340 new_crypt = NULL;
341
342 printk(KERN_WARNING "%s: could not initialize WEP: "
343 "load module ieee80211_crypt_wep\n",
344 dev->name);
345 return -EOPNOTSUPP;
346 }
347 *crypt = new_crypt;
348 }
349
350 /* If a new key was provided, set it up */
351 if (erq->length > 0) {
352 len = erq->length <= 5 ? 5 : 13;
353 memcpy(sec.keys[key], keybuf, erq->length);
354 if (len > erq->length)
355 memset(sec.keys[key] + erq->length, 0,
356 len - erq->length);
357 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
358 key, escape_essid(sec.keys[key], len),
359 erq->length, len);
360 sec.key_sizes[key] = len;
361 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
362 (*crypt)->priv);
363 sec.flags |= (1 << key);
364 /* This ensures a key will be activated if no key is
365 * explicitely set */
366 if (key == sec.active_key)
367 sec.flags |= SEC_ACTIVE_KEY;
368 } else {
369 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
370 NULL, (*crypt)->priv);
371 if (len == 0) {
372 /* Set a default key of all 0 */
373 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
374 key);
375 memset(sec.keys[key], 0, 13);
376 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
377 (*crypt)->priv);
378 sec.key_sizes[key] = 13;
379 sec.flags |= (1 << key);
380 }
381
382 /* No key data - just set the default TX key index */
383 if (key_provided) {
384 IEEE80211_DEBUG_WX(
385 "Setting key %d to default Tx key.\n", key);
386 ieee->tx_keyidx = key;
387 sec.active_key = key;
388 sec.flags |= SEC_ACTIVE_KEY;
389 }
390 }
391
392 done:
393 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
394 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
395 sec.flags |= SEC_AUTH_MODE;
396 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
397 "OPEN" : "SHARED KEY");
398
399 /* For now we just support WEP, so only set that security level...
400 * TODO: When WPA is added this is one place that needs to change */
401 sec.flags |= SEC_LEVEL;
402 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
403
404 if (ieee->set_security)
405 ieee->set_security(dev, &sec);
406
407 /* Do not reset port if card is in Managed mode since resetting will
408 * generate new IEEE 802.11 authentication which may end up in looping
409 * with IEEE 802.1X. If your hardware requires a reset after WEP
410 * configuration (for example... Prism2), implement the reset_port in
411 * the callbacks structures used to initialize the 802.11 stack. */
412 if (ieee->reset_on_keychange &&
413 ieee->iw_mode != IW_MODE_INFRA &&
414 ieee->reset_port && ieee->reset_port(dev)) {
415 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
416 return -EINVAL;
417 }
418 return 0;
419}
420
421int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
422 struct iw_request_info *info,
423 union iwreq_data *wrqu, char *keybuf)
424{
425 struct iw_point *erq = &(wrqu->encoding);
426 int len, key;
427 struct ieee80211_crypt_data *crypt;
428
429 IEEE80211_DEBUG_WX("GET_ENCODE\n");
430
431 key = erq->flags & IW_ENCODE_INDEX;
432 if (key) {
433 if (key > WEP_KEYS)
434 return -EINVAL;
435 key--;
436 } else
437 key = ieee->tx_keyidx;
438
439 crypt = ieee->crypt[key];
440 erq->flags = key + 1;
441
442 if (crypt == NULL || crypt->ops == NULL) {
443 erq->length = 0;
444 erq->flags |= IW_ENCODE_DISABLED;
445 return 0;
446 }
447
448 if (strcmp(crypt->ops->name, "WEP") != 0) {
449 /* only WEP is supported with wireless extensions, so just
450 * report that encryption is used */
451 erq->length = 0;
452 erq->flags |= IW_ENCODE_ENABLED;
453 return 0;
454 }
455
456 len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
457 erq->length = (len >= 0 ? len : 0);
458
459 erq->flags |= IW_ENCODE_ENABLED;
460
461 if (ieee->open_wep)
462 erq->flags |= IW_ENCODE_OPEN;
463 else
464 erq->flags |= IW_ENCODE_RESTRICTED;
465
466 return 0;
467}
468
469EXPORT_SYMBOL(ieee80211_wx_get_scan);
470EXPORT_SYMBOL(ieee80211_wx_set_encode);
471EXPORT_SYMBOL(ieee80211_wx_get_encode);