aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/ieee80211/Kconfig69
-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.c273
-rw-r--r--net/ieee80211/ieee80211_rx.c1205
-rw-r--r--net/ieee80211/ieee80211_tx.c447
-rw-r--r--net/ieee80211/ieee80211_wx.c471
12 files changed, 4187 insertions, 0 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 40a31ba86d2c..32327d0a56ad 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -212,6 +212,7 @@ endmenu
212source "net/ax25/Kconfig" 212source "net/ax25/Kconfig"
213source "net/irda/Kconfig" 213source "net/irda/Kconfig"
214source "net/bluetooth/Kconfig" 214source "net/bluetooth/Kconfig"
215source "net/ieee80211/Kconfig"
215 216
216endif # if NET 217endif # if NET
217endmenu # Networking 218endmenu # Networking
diff --git a/net/Makefile b/net/Makefile
index 8e2bdc025ab8..83bc52d87bae 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_DECNET) += decnet/
42obj-$(CONFIG_ECONET) += econet/ 42obj-$(CONFIG_ECONET) += econet/
43obj-$(CONFIG_VLAN_8021Q) += 8021q/ 43obj-$(CONFIG_VLAN_8021Q) += 8021q/
44obj-$(CONFIG_IP_SCTP) += sctp/ 44obj-$(CONFIG_IP_SCTP) += sctp/
45obj-$(CONFIG_IEEE80211) += ieee80211/
45 46
46ifeq ($(CONFIG_NET),y) 47ifeq ($(CONFIG_NET),y)
47obj-$(CONFIG_SYSCTL) += sysctl_net.o 48obj-$(CONFIG_SYSCTL) += sysctl_net.o
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
new file mode 100644
index 000000000000..961c711eda97
--- /dev/null
+++ b/net/ieee80211/Kconfig
@@ -0,0 +1,69 @@
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
48 select CRYPTO_AES
49 ---help---
50 Include software based cipher suites in support of IEEE 802.11i
51 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled
52 networks.
53
54 This can be compiled as a modules and it will be called
55 "ieee80211_crypt_ccmp".
56
57config IEEE80211_CRYPT_TKIP
58 tristate "IEEE 802.11i TKIP encryption"
59 depends on IEEE80211
60 select CRYPTO
61 select CRYPTO_MICHAEL_MIC
62 ---help---
63 Include software based cipher suites in support of IEEE 802.11i
64 (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled
65 networks.
66
67 This can be compiled as a modules and it will be called
68 "ieee80211_crypt_tkip".
69
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..11d15573b26a
--- /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
62static void 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..e0802b8755a0
--- /dev/null
+++ b/net/ieee80211/ieee80211_module.c
@@ -0,0 +1,273 @@
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/proc_fs.h>
44#include <linux/skbuff.h>
45#include <linux/slab.h>
46#include <linux/tcp.h>
47#include <linux/types.h>
48#include <linux/version.h>
49#include <linux/wireless.h>
50#include <linux/etherdevice.h>
51#include <asm/uaccess.h>
52#include <net/arp.h>
53
54#include <net/ieee80211.h>
55
56MODULE_DESCRIPTION("802.11 data/management/control stack");
57MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
58MODULE_LICENSE("GPL");
59
60#define DRV_NAME "ieee80211"
61
62static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
63{
64 if (ieee->networks)
65 return 0;
66
67 ieee->networks = kmalloc(
68 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
69 GFP_KERNEL);
70 if (!ieee->networks) {
71 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
72 ieee->dev->name);
73 return -ENOMEM;
74 }
75
76 memset(ieee->networks, 0,
77 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
78
79 return 0;
80}
81
82static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
83{
84 if (!ieee->networks)
85 return;
86 kfree(ieee->networks);
87 ieee->networks = NULL;
88}
89
90static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
91{
92 int i;
93
94 INIT_LIST_HEAD(&ieee->network_free_list);
95 INIT_LIST_HEAD(&ieee->network_list);
96 for (i = 0; i < MAX_NETWORK_COUNT; i++)
97 list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
98}
99
100
101struct net_device *alloc_ieee80211(int sizeof_priv)
102{
103 struct ieee80211_device *ieee;
104 struct net_device *dev;
105 int err;
106
107 IEEE80211_DEBUG_INFO("Initializing...\n");
108
109 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
110 if (!dev) {
111 IEEE80211_ERROR("Unable to network device.\n");
112 goto failed;
113 }
114 ieee = netdev_priv(dev);
115 dev->hard_start_xmit = ieee80211_xmit;
116
117 ieee->dev = dev;
118
119 err = ieee80211_networks_allocate(ieee);
120 if (err) {
121 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
122 err);
123 goto failed;
124 }
125 ieee80211_networks_initialize(ieee);
126
127 /* Default fragmentation threshold is maximum payload size */
128 ieee->fts = DEFAULT_FTS;
129 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
130 ieee->open_wep = 1;
131
132 /* Default to enabling full open WEP with host based encrypt/decrypt */
133 ieee->host_encrypt = 1;
134 ieee->host_decrypt = 1;
135 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
136
137 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
138 init_timer(&ieee->crypt_deinit_timer);
139 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
140 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
141
142 spin_lock_init(&ieee->lock);
143
144 ieee->wpa_enabled = 0;
145 ieee->tkip_countermeasures = 0;
146 ieee->drop_unencrypted = 0;
147 ieee->privacy_invoked = 0;
148 ieee->ieee802_1x = 1;
149
150 return dev;
151
152 failed:
153 if (dev)
154 free_netdev(dev);
155 return NULL;
156}
157
158
159void free_ieee80211(struct net_device *dev)
160{
161 struct ieee80211_device *ieee = netdev_priv(dev);
162
163 int i;
164
165 del_timer_sync(&ieee->crypt_deinit_timer);
166 ieee80211_crypt_deinit_entries(ieee, 1);
167
168 for (i = 0; i < WEP_KEYS; i++) {
169 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
170 if (crypt) {
171 if (crypt->ops) {
172 crypt->ops->deinit(crypt->priv);
173 module_put(crypt->ops->owner);
174 }
175 kfree(crypt);
176 ieee->crypt[i] = NULL;
177 }
178 }
179
180 ieee80211_networks_free(ieee);
181 free_netdev(dev);
182}
183
184#ifdef CONFIG_IEEE80211_DEBUG
185
186static int debug = 0;
187u32 ieee80211_debug_level = 0;
188struct proc_dir_entry *ieee80211_proc = NULL;
189
190static int show_debug_level(char *page, char **start, off_t offset,
191 int count, int *eof, void *data)
192{
193 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
194}
195
196static int store_debug_level(struct file *file, const char __user *buffer,
197 unsigned long count, void *data)
198{
199 char buf[] = "0x00000000";
200 char *p = (char *)buf;
201 unsigned long val;
202
203 if (count > sizeof(buf) - 1)
204 count = sizeof(buf) - 1;
205
206 if (copy_from_user(buf, buffer, count))
207 return count;
208 buf[count] = 0;
209 /*
210 * what a FPOS... What, sscanf(buf, "%i", &val) would be too
211 * scary?
212 */
213 if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
214 p++;
215 if (p[0] == 'x' || p[0] == 'X')
216 p++;
217 val = simple_strtoul(p, &p, 16);
218 } else
219 val = simple_strtoul(p, &p, 10);
220 if (p == buf)
221 printk(KERN_INFO DRV_NAME
222 ": %s is not in hex or decimal form.\n", buf);
223 else
224 ieee80211_debug_level = val;
225
226 return strlen(buf);
227}
228
229static int __init ieee80211_init(void)
230{
231 struct proc_dir_entry *e;
232
233 ieee80211_debug_level = debug;
234 ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
235 if (ieee80211_proc == NULL) {
236 IEEE80211_ERROR("Unable to create " DRV_NAME
237 " proc directory\n");
238 return -EIO;
239 }
240 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
241 ieee80211_proc);
242 if (!e) {
243 remove_proc_entry(DRV_NAME, proc_net);
244 ieee80211_proc = NULL;
245 return -EIO;
246 }
247 e->read_proc = show_debug_level;
248 e->write_proc = store_debug_level;
249 e->data = NULL;
250
251 return 0;
252}
253
254static void __exit ieee80211_exit(void)
255{
256 if (ieee80211_proc) {
257 remove_proc_entry("debug_level", ieee80211_proc);
258 remove_proc_entry(DRV_NAME, proc_net);
259 ieee80211_proc = NULL;
260 }
261}
262
263#include <linux/moduleparam.h>
264module_param(debug, int, 0444);
265MODULE_PARM_DESC(debug, "debug output mask");
266
267
268module_exit(ieee80211_exit);
269module_init(ieee80211_init);
270#endif
271
272EXPORT_SYMBOL(alloc_ieee80211);
273EXPORT_SYMBOL(free_ieee80211);
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
new file mode 100644
index 000000000000..0dd102993ef4
--- /dev/null
+++ b/net/ieee80211/ieee80211_rx.c
@@ -0,0 +1,1205 @@
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/proc_fs.h>
27#include <linux/skbuff.h>
28#include <linux/slab.h>
29#include <linux/tcp.h>
30#include <linux/types.h>
31#include <linux/version.h>
32#include <linux/wireless.h>
33#include <linux/etherdevice.h>
34#include <asm/uaccess.h>
35#include <linux/ctype.h>
36
37#include <net/ieee80211.h>
38
39static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
40 struct sk_buff *skb,
41 struct ieee80211_rx_stats *rx_stats)
42{
43 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
44 u16 fc = le16_to_cpu(hdr->frame_ctl);
45
46 skb->dev = ieee->dev;
47 skb->mac.raw = skb->data;
48 skb_pull(skb, ieee80211_get_hdrlen(fc));
49 skb->pkt_type = PACKET_OTHERHOST;
50 skb->protocol = __constant_htons(ETH_P_80211_RAW);
51 memset(skb->cb, 0, sizeof(skb->cb));
52 netif_rx(skb);
53}
54
55
56/* Called only as a tasklet (software IRQ) */
57static struct ieee80211_frag_entry *
58ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
59 unsigned int frag, u8 *src, u8 *dst)
60{
61 struct ieee80211_frag_entry *entry;
62 int i;
63
64 for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
65 entry = &ieee->frag_cache[i];
66 if (entry->skb != NULL &&
67 time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
68 IEEE80211_DEBUG_FRAG(
69 "expiring fragment cache entry "
70 "seq=%u last_frag=%u\n",
71 entry->seq, entry->last_frag);
72 dev_kfree_skb_any(entry->skb);
73 entry->skb = NULL;
74 }
75
76 if (entry->skb != NULL && entry->seq == seq &&
77 (entry->last_frag + 1 == frag || frag == -1) &&
78 memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
79 memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
80 return entry;
81 }
82
83 return NULL;
84}
85
86/* Called only as a tasklet (software IRQ) */
87static struct sk_buff *
88ieee80211_frag_cache_get(struct ieee80211_device *ieee,
89 struct ieee80211_hdr *hdr)
90{
91 struct sk_buff *skb = NULL;
92 u16 sc;
93 unsigned int frag, seq;
94 struct ieee80211_frag_entry *entry;
95
96 sc = le16_to_cpu(hdr->seq_ctl);
97 frag = WLAN_GET_SEQ_FRAG(sc);
98 seq = WLAN_GET_SEQ_SEQ(sc);
99
100 if (frag == 0) {
101 /* Reserve enough space to fit maximum frame length */
102 skb = dev_alloc_skb(ieee->dev->mtu +
103 sizeof(struct ieee80211_hdr) +
104 8 /* LLC */ +
105 2 /* alignment */ +
106 8 /* WEP */ + ETH_ALEN /* WDS */);
107 if (skb == NULL)
108 return NULL;
109
110 entry = &ieee->frag_cache[ieee->frag_next_idx];
111 ieee->frag_next_idx++;
112 if (ieee->frag_next_idx >= IEEE80211_FRAG_CACHE_LEN)
113 ieee->frag_next_idx = 0;
114
115 if (entry->skb != NULL)
116 dev_kfree_skb_any(entry->skb);
117
118 entry->first_frag_time = jiffies;
119 entry->seq = seq;
120 entry->last_frag = frag;
121 entry->skb = skb;
122 memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
123 memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
124 } else {
125 /* received a fragment of a frame for which the head fragment
126 * should have already been received */
127 entry = ieee80211_frag_cache_find(ieee, seq, frag, hdr->addr2,
128 hdr->addr1);
129 if (entry != NULL) {
130 entry->last_frag = frag;
131 skb = entry->skb;
132 }
133 }
134
135 return skb;
136}
137
138
139/* Called only as a tasklet (software IRQ) */
140static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
141 struct ieee80211_hdr *hdr)
142{
143 u16 sc;
144 unsigned int seq;
145 struct ieee80211_frag_entry *entry;
146
147 sc = le16_to_cpu(hdr->seq_ctl);
148 seq = WLAN_GET_SEQ_SEQ(sc);
149
150 entry = ieee80211_frag_cache_find(ieee, seq, -1, hdr->addr2,
151 hdr->addr1);
152
153 if (entry == NULL) {
154 IEEE80211_DEBUG_FRAG(
155 "could not invalidate fragment cache "
156 "entry (seq=%u)\n", seq);
157 return -1;
158 }
159
160 entry->skb = NULL;
161 return 0;
162}
163
164
165#ifdef NOT_YET
166/* ieee80211_rx_frame_mgtmt
167 *
168 * Responsible for handling management control frames
169 *
170 * Called by ieee80211_rx */
171static inline int
172ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
173 struct ieee80211_rx_stats *rx_stats, u16 type,
174 u16 stype)
175{
176 if (ieee->iw_mode == IW_MODE_MASTER) {
177 printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
178 ieee->dev->name);
179 return 0;
180/*
181 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *)
182 skb->data);*/
183 }
184
185 if (ieee->hostapd && type == WLAN_FC_TYPE_MGMT) {
186 if (stype == WLAN_FC_STYPE_BEACON &&
187 ieee->iw_mode == IW_MODE_MASTER) {
188 struct sk_buff *skb2;
189 /* Process beacon frames also in kernel driver to
190 * update STA(AP) table statistics */
191 skb2 = skb_clone(skb, GFP_ATOMIC);
192 if (skb2)
193 hostap_rx(skb2->dev, skb2, rx_stats);
194 }
195
196 /* send management frames to the user space daemon for
197 * processing */
198 ieee->apdevstats.rx_packets++;
199 ieee->apdevstats.rx_bytes += skb->len;
200 prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
201 return 0;
202 }
203
204 if (ieee->iw_mode == IW_MODE_MASTER) {
205 if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
206 printk(KERN_DEBUG "%s: unknown management frame "
207 "(type=0x%02x, stype=0x%02x) dropped\n",
208 skb->dev->name, type, stype);
209 return -1;
210 }
211
212 hostap_rx(skb->dev, skb, rx_stats);
213 return 0;
214 }
215
216 printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
217 "received in non-Host AP mode\n", skb->dev->name);
218 return -1;
219}
220#endif
221
222
223/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
224/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
225static unsigned char rfc1042_header[] =
226{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
227/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
228static unsigned char bridge_tunnel_header[] =
229{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
230/* No encapsulation header if EtherType < 0x600 (=length) */
231
232/* Called by ieee80211_rx_frame_decrypt */
233static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
234 struct sk_buff *skb)
235{
236 struct net_device *dev = ieee->dev;
237 u16 fc, ethertype;
238 struct ieee80211_hdr *hdr;
239 u8 *pos;
240
241 if (skb->len < 24)
242 return 0;
243
244 hdr = (struct ieee80211_hdr *) skb->data;
245 fc = le16_to_cpu(hdr->frame_ctl);
246
247 /* check that the frame is unicast frame to us */
248 if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
249 IEEE80211_FCTL_TODS &&
250 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
251 memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
252 /* ToDS frame with own addr BSSID and DA */
253 } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
254 IEEE80211_FCTL_FROMDS &&
255 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
256 /* FromDS frame with own addr as DA */
257 } else
258 return 0;
259
260 if (skb->len < 24 + 8)
261 return 0;
262
263 /* check for port access entity Ethernet type */
264 pos = skb->data + 24;
265 ethertype = (pos[6] << 8) | pos[7];
266 if (ethertype == ETH_P_PAE)
267 return 1;
268
269 return 0;
270}
271
272/* Called only as a tasklet (software IRQ), by ieee80211_rx */
273static inline int
274ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
275 struct ieee80211_crypt_data *crypt)
276{
277 struct ieee80211_hdr *hdr;
278 int res, hdrlen;
279
280 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
281 return 0;
282
283 hdr = (struct ieee80211_hdr *) skb->data;
284 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
285
286#ifdef CONFIG_IEEE80211_CRYPT_TKIP
287 if (ieee->tkip_countermeasures &&
288 strcmp(crypt->ops->name, "TKIP") == 0) {
289 if (net_ratelimit()) {
290 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
291 "received packet from " MAC_FMT "\n",
292 ieee->dev->name, MAC_ARG(hdr->addr2));
293 }
294 return -1;
295 }
296#endif
297
298 atomic_inc(&crypt->refcnt);
299 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
300 atomic_dec(&crypt->refcnt);
301 if (res < 0) {
302 IEEE80211_DEBUG_DROP(
303 "decryption failed (SA=" MAC_FMT
304 ") res=%d\n", MAC_ARG(hdr->addr2), res);
305 if (res == -2)
306 IEEE80211_DEBUG_DROP("Decryption failed ICV "
307 "mismatch (key %d)\n",
308 skb->data[hdrlen + 3] >> 6);
309 ieee->ieee_stats.rx_discards_undecryptable++;
310 return -1;
311 }
312
313 return res;
314}
315
316
317/* Called only as a tasklet (software IRQ), by ieee80211_rx */
318static inline int
319ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
320 int keyidx, struct ieee80211_crypt_data *crypt)
321{
322 struct ieee80211_hdr *hdr;
323 int res, hdrlen;
324
325 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
326 return 0;
327
328 hdr = (struct ieee80211_hdr *) skb->data;
329 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
330
331 atomic_inc(&crypt->refcnt);
332 res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
333 atomic_dec(&crypt->refcnt);
334 if (res < 0) {
335 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
336 " (SA=" MAC_FMT " keyidx=%d)\n",
337 ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
338 return -1;
339 }
340
341 return 0;
342}
343
344
345/* All received frames are sent to this function. @skb contains the frame in
346 * IEEE 802.11 format, i.e., in the format it was sent over air.
347 * This function is called only as a tasklet (software IRQ). */
348int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
349 struct ieee80211_rx_stats *rx_stats)
350{
351 struct net_device *dev = ieee->dev;
352 struct ieee80211_hdr *hdr;
353 size_t hdrlen;
354 u16 fc, type, stype, sc;
355 struct net_device_stats *stats;
356 unsigned int frag;
357 u8 *payload;
358 u16 ethertype;
359#ifdef NOT_YET
360 struct net_device *wds = NULL;
361 struct sk_buff *skb2 = NULL;
362 struct net_device *wds = NULL;
363 int frame_authorized = 0;
364 int from_assoc_ap = 0;
365 void *sta = NULL;
366#endif
367 u8 dst[ETH_ALEN];
368 u8 src[ETH_ALEN];
369 struct ieee80211_crypt_data *crypt = NULL;
370 int keyidx = 0;
371
372 hdr = (struct ieee80211_hdr *)skb->data;
373 stats = &ieee->stats;
374
375 if (skb->len < 10) {
376 printk(KERN_INFO "%s: SKB length < 10\n",
377 dev->name);
378 goto rx_dropped;
379 }
380
381 fc = le16_to_cpu(hdr->frame_ctl);
382 type = WLAN_FC_GET_TYPE(fc);
383 stype = WLAN_FC_GET_STYPE(fc);
384 sc = le16_to_cpu(hdr->seq_ctl);
385 frag = WLAN_GET_SEQ_FRAG(sc);
386 hdrlen = ieee80211_get_hdrlen(fc);
387
388#ifdef NOT_YET
389#if WIRELESS_EXT > 15
390 /* Put this code here so that we avoid duplicating it in all
391 * Rx paths. - Jean II */
392#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
393 /* If spy monitoring on */
394 if (iface->spy_data.spy_number > 0) {
395 struct iw_quality wstats;
396 wstats.level = rx_stats->signal;
397 wstats.noise = rx_stats->noise;
398 wstats.updated = 6; /* No qual value */
399 /* Update spy records */
400 wireless_spy_update(dev, hdr->addr2, &wstats);
401 }
402#endif /* IW_WIRELESS_SPY */
403#endif /* WIRELESS_EXT > 15 */
404 hostap_update_rx_stats(local->ap, hdr, rx_stats);
405#endif
406
407#if WIRELESS_EXT > 15
408 if (ieee->iw_mode == IW_MODE_MONITOR) {
409 ieee80211_monitor_rx(ieee, skb, rx_stats);
410 stats->rx_packets++;
411 stats->rx_bytes += skb->len;
412 return 1;
413 }
414#endif
415
416 if (ieee->host_decrypt) {
417 int idx = 0;
418 if (skb->len >= hdrlen + 3)
419 idx = skb->data[hdrlen + 3] >> 6;
420 crypt = ieee->crypt[idx];
421#ifdef NOT_YET
422 sta = NULL;
423
424 /* Use station specific key to override default keys if the
425 * receiver address is a unicast address ("individual RA"). If
426 * bcrx_sta_key parameter is set, station specific key is used
427 * even with broad/multicast targets (this is against IEEE
428 * 802.11, but makes it easier to use different keys with
429 * stations that do not support WEP key mapping). */
430
431 if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
432 (void) hostap_handle_sta_crypto(local, hdr, &crypt,
433 &sta);
434#endif
435
436 /* allow NULL decrypt to indicate an station specific override
437 * for default encryption */
438 if (crypt && (crypt->ops == NULL ||
439 crypt->ops->decrypt_mpdu == NULL))
440 crypt = NULL;
441
442 if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
443 /* This seems to be triggered by some (multicast?)
444 * frames from other than current BSS, so just drop the
445 * frames silently instead of filling system log with
446 * these reports. */
447 IEEE80211_DEBUG_DROP("Decryption failed (not set)"
448 " (SA=" MAC_FMT ")\n",
449 MAC_ARG(hdr->addr2));
450 ieee->ieee_stats.rx_discards_undecryptable++;
451 goto rx_dropped;
452 }
453 }
454
455#ifdef NOT_YET
456 if (type != WLAN_FC_TYPE_DATA) {
457 if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH &&
458 fc & IEEE80211_FCTL_WEP && ieee->host_decrypt &&
459 (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0)
460 {
461 printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
462 "from " MAC_FMT "\n", dev->name,
463 MAC_ARG(hdr->addr2));
464 /* TODO: could inform hostapd about this so that it
465 * could send auth failure report */
466 goto rx_dropped;
467 }
468
469 if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
470 goto rx_dropped;
471 else
472 goto rx_exit;
473 }
474#endif
475
476 /* Data frame - extract src/dst addresses */
477 if (skb->len < IEEE80211_3ADDR_LEN)
478 goto rx_dropped;
479
480 switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
481 case IEEE80211_FCTL_FROMDS:
482 memcpy(dst, hdr->addr1, ETH_ALEN);
483 memcpy(src, hdr->addr3, ETH_ALEN);
484 break;
485 case IEEE80211_FCTL_TODS:
486 memcpy(dst, hdr->addr3, ETH_ALEN);
487 memcpy(src, hdr->addr2, ETH_ALEN);
488 break;
489 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
490 if (skb->len < IEEE80211_4ADDR_LEN)
491 goto rx_dropped;
492 memcpy(dst, hdr->addr3, ETH_ALEN);
493 memcpy(src, hdr->addr4, ETH_ALEN);
494 break;
495 case 0:
496 memcpy(dst, hdr->addr1, ETH_ALEN);
497 memcpy(src, hdr->addr2, ETH_ALEN);
498 break;
499 }
500
501#ifdef NOT_YET
502 if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
503 goto rx_dropped;
504 if (wds) {
505 skb->dev = dev = wds;
506 stats = hostap_get_stats(dev);
507 }
508
509 if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
510 (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS &&
511 ieee->stadev &&
512 memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) {
513 /* Frame from BSSID of the AP for which we are a client */
514 skb->dev = dev = ieee->stadev;
515 stats = hostap_get_stats(dev);
516 from_assoc_ap = 1;
517 }
518#endif
519
520 dev->last_rx = jiffies;
521
522#ifdef NOT_YET
523 if ((ieee->iw_mode == IW_MODE_MASTER ||
524 ieee->iw_mode == IW_MODE_REPEAT) &&
525 !from_assoc_ap) {
526 switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
527 wds != NULL)) {
528 case AP_RX_CONTINUE_NOT_AUTHORIZED:
529 frame_authorized = 0;
530 break;
531 case AP_RX_CONTINUE:
532 frame_authorized = 1;
533 break;
534 case AP_RX_DROP:
535 goto rx_dropped;
536 case AP_RX_EXIT:
537 goto rx_exit;
538 }
539 }
540#endif
541
542 /* Nullfunc frames may have PS-bit set, so they must be passed to
543 * hostap_handle_sta_rx() before being dropped here. */
544 if (stype != IEEE80211_STYPE_DATA &&
545 stype != IEEE80211_STYPE_DATA_CFACK &&
546 stype != IEEE80211_STYPE_DATA_CFPOLL &&
547 stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
548 if (stype != IEEE80211_STYPE_NULLFUNC)
549 IEEE80211_DEBUG_DROP(
550 "RX: dropped data frame "
551 "with no data (type=0x%02x, "
552 "subtype=0x%02x, len=%d)\n",
553 type, stype, skb->len);
554 goto rx_dropped;
555 }
556
557 /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
558
559 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
560 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
561 goto rx_dropped;
562
563 hdr = (struct ieee80211_hdr *) skb->data;
564
565 /* skb: hdr + (possibly fragmented) plaintext payload */
566 // PR: FIXME: hostap has additional conditions in the "if" below:
567 // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
568 if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
569 int flen;
570 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
571 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
572
573 if (!frag_skb) {
574 IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
575 "Rx cannot get skb from fragment "
576 "cache (morefrag=%d seq=%u frag=%u)\n",
577 (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
578 WLAN_GET_SEQ_SEQ(sc), frag);
579 goto rx_dropped;
580 }
581
582 flen = skb->len;
583 if (frag != 0)
584 flen -= hdrlen;
585
586 if (frag_skb->tail + flen > frag_skb->end) {
587 printk(KERN_WARNING "%s: host decrypted and "
588 "reassembled frame did not fit skb\n",
589 dev->name);
590 ieee80211_frag_cache_invalidate(ieee, hdr);
591 goto rx_dropped;
592 }
593
594 if (frag == 0) {
595 /* copy first fragment (including full headers) into
596 * beginning of the fragment cache skb */
597 memcpy(skb_put(frag_skb, flen), skb->data, flen);
598 } else {
599 /* append frame payload to the end of the fragment
600 * cache skb */
601 memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
602 flen);
603 }
604 dev_kfree_skb_any(skb);
605 skb = NULL;
606
607 if (fc & IEEE80211_FCTL_MOREFRAGS) {
608 /* more fragments expected - leave the skb in fragment
609 * cache for now; it will be delivered to upper layers
610 * after all fragments have been received */
611 goto rx_exit;
612 }
613
614 /* this was the last fragment and the frame will be
615 * delivered, so remove skb from fragment cache */
616 skb = frag_skb;
617 hdr = (struct ieee80211_hdr *) skb->data;
618 ieee80211_frag_cache_invalidate(ieee, hdr);
619 }
620
621 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
622 * encrypted/authenticated */
623 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
624 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
625 goto rx_dropped;
626
627 hdr = (struct ieee80211_hdr *) skb->data;
628 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
629 if (/*ieee->ieee802_1x &&*/
630 ieee80211_is_eapol_frame(ieee, skb)) {
631#ifdef CONFIG_IEEE80211_DEBUG
632 /* pass unencrypted EAPOL frames even if encryption is
633 * configured */
634 struct eapol *eap = (struct eapol *)(skb->data +
635 24);
636 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
637 eap_get_type(eap->type));
638#endif
639 } else {
640 IEEE80211_DEBUG_DROP(
641 "encryption configured, but RX "
642 "frame not encrypted (SA=" MAC_FMT ")\n",
643 MAC_ARG(hdr->addr2));
644 goto rx_dropped;
645 }
646 }
647
648#ifdef CONFIG_IEEE80211_DEBUG
649 if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
650 ieee80211_is_eapol_frame(ieee, skb)) {
651 struct eapol *eap = (struct eapol *)(skb->data +
652 24);
653 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
654 eap_get_type(eap->type));
655 }
656#endif
657
658 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
659 !ieee80211_is_eapol_frame(ieee, skb)) {
660 IEEE80211_DEBUG_DROP(
661 "dropped unencrypted RX data "
662 "frame from " MAC_FMT
663 " (drop_unencrypted=1)\n",
664 MAC_ARG(hdr->addr2));
665 goto rx_dropped;
666 }
667
668 /* skb: hdr + (possible reassembled) full plaintext payload */
669
670 payload = skb->data + hdrlen;
671 ethertype = (payload[6] << 8) | payload[7];
672
673#ifdef NOT_YET
674 /* If IEEE 802.1X is used, check whether the port is authorized to send
675 * the received frame. */
676 if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) {
677 if (ethertype == ETH_P_PAE) {
678 printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n",
679 dev->name);
680 if (ieee->hostapd && ieee->apdev) {
681 /* Send IEEE 802.1X frames to the user
682 * space daemon for processing */
683 prism2_rx_80211(ieee->apdev, skb, rx_stats,
684 PRISM2_RX_MGMT);
685 ieee->apdevstats.rx_packets++;
686 ieee->apdevstats.rx_bytes += skb->len;
687 goto rx_exit;
688 }
689 } else if (!frame_authorized) {
690 printk(KERN_DEBUG "%s: dropped frame from "
691 "unauthorized port (IEEE 802.1X): "
692 "ethertype=0x%04x\n",
693 dev->name, ethertype);
694 goto rx_dropped;
695 }
696 }
697#endif
698
699 /* convert hdr + possible LLC headers into Ethernet header */
700 if (skb->len - hdrlen >= 8 &&
701 ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
702 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
703 memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
704 /* remove RFC1042 or Bridge-Tunnel encapsulation and
705 * replace EtherType */
706 skb_pull(skb, hdrlen + SNAP_SIZE);
707 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
708 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
709 } else {
710 u16 len;
711 /* Leave Ethernet header part of hdr and full payload */
712 skb_pull(skb, hdrlen);
713 len = htons(skb->len);
714 memcpy(skb_push(skb, 2), &len, 2);
715 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
716 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
717 }
718
719#ifdef NOT_YET
720 if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
721 IEEE80211_FCTL_TODS) &&
722 skb->len >= ETH_HLEN + ETH_ALEN) {
723 /* Non-standard frame: get addr4 from its bogus location after
724 * the payload */
725 memcpy(skb->data + ETH_ALEN,
726 skb->data + skb->len - ETH_ALEN, ETH_ALEN);
727 skb_trim(skb, skb->len - ETH_ALEN);
728 }
729#endif
730
731 stats->rx_packets++;
732 stats->rx_bytes += skb->len;
733
734#ifdef NOT_YET
735 if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
736 ieee->ap->bridge_packets) {
737 if (dst[0] & 0x01) {
738 /* copy multicast frame both to the higher layers and
739 * to the wireless media */
740 ieee->ap->bridged_multicast++;
741 skb2 = skb_clone(skb, GFP_ATOMIC);
742 if (skb2 == NULL)
743 printk(KERN_DEBUG "%s: skb_clone failed for "
744 "multicast frame\n", dev->name);
745 } else if (hostap_is_sta_assoc(ieee->ap, dst)) {
746 /* send frame directly to the associated STA using
747 * wireless media and not passing to higher layers */
748 ieee->ap->bridged_unicast++;
749 skb2 = skb;
750 skb = NULL;
751 }
752 }
753
754 if (skb2 != NULL) {
755 /* send to wireless media */
756 skb2->protocol = __constant_htons(ETH_P_802_3);
757 skb2->mac.raw = skb2->nh.raw = skb2->data;
758 /* skb2->nh.raw = skb2->data + ETH_HLEN; */
759 skb2->dev = dev;
760 dev_queue_xmit(skb2);
761 }
762
763#endif
764
765 if (skb) {
766 skb->protocol = eth_type_trans(skb, dev);
767 memset(skb->cb, 0, sizeof(skb->cb));
768 skb->dev = dev;
769 skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
770 netif_rx(skb);
771 }
772
773 rx_exit:
774#ifdef NOT_YET
775 if (sta)
776 hostap_handle_sta_release(sta);
777#endif
778 return 1;
779
780 rx_dropped:
781 stats->rx_dropped++;
782
783 /* Returning 0 indicates to caller that we have not handled the SKB--
784 * so it is still allocated and can be used again by underlying
785 * hardware as a DMA target */
786 return 0;
787}
788
789#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
790
791static inline int ieee80211_is_ofdm_rate(u8 rate)
792{
793 switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
794 case IEEE80211_OFDM_RATE_6MB:
795 case IEEE80211_OFDM_RATE_9MB:
796 case IEEE80211_OFDM_RATE_12MB:
797 case IEEE80211_OFDM_RATE_18MB:
798 case IEEE80211_OFDM_RATE_24MB:
799 case IEEE80211_OFDM_RATE_36MB:
800 case IEEE80211_OFDM_RATE_48MB:
801 case IEEE80211_OFDM_RATE_54MB:
802 return 1;
803 }
804 return 0;
805}
806
807
808static inline int ieee80211_network_init(
809 struct ieee80211_device *ieee,
810 struct ieee80211_probe_response *beacon,
811 struct ieee80211_network *network,
812 struct ieee80211_rx_stats *stats)
813{
814#ifdef CONFIG_IEEE80211_DEBUG
815 char rates_str[64];
816 char *p;
817#endif
818 struct ieee80211_info_element *info_element;
819 u16 left;
820 u8 i;
821
822 /* Pull out fixed field data */
823 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
824 network->capability = beacon->capability;
825 network->last_scanned = jiffies;
826 network->time_stamp[0] = beacon->time_stamp[0];
827 network->time_stamp[1] = beacon->time_stamp[1];
828 network->beacon_interval = beacon->beacon_interval;
829 /* Where to pull this? beacon->listen_interval;*/
830 network->listen_interval = 0x0A;
831 network->rates_len = network->rates_ex_len = 0;
832 network->last_associate = 0;
833 network->ssid_len = 0;
834 network->flags = 0;
835 network->atim_window = 0;
836
837 if (stats->freq == IEEE80211_52GHZ_BAND) {
838 /* for A band (No DS info) */
839 network->channel = stats->received_channel;
840 } else
841 network->flags |= NETWORK_HAS_CCK;
842
843 network->wpa_ie_len = 0;
844 network->rsn_ie_len = 0;
845
846 info_element = &beacon->info_element;
847 left = stats->len - ((void *)info_element - (void *)beacon);
848 while (left >= sizeof(struct ieee80211_info_element_hdr)) {
849 if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
850 IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
851 info_element->len + sizeof(struct ieee80211_info_element),
852 left);
853 return 1;
854 }
855
856 switch (info_element->id) {
857 case MFIE_TYPE_SSID:
858 if (ieee80211_is_empty_essid(info_element->data,
859 info_element->len)) {
860 network->flags |= NETWORK_EMPTY_ESSID;
861 break;
862 }
863
864 network->ssid_len = min(info_element->len,
865 (u8)IW_ESSID_MAX_SIZE);
866 memcpy(network->ssid, info_element->data, network->ssid_len);
867 if (network->ssid_len < IW_ESSID_MAX_SIZE)
868 memset(network->ssid + network->ssid_len, 0,
869 IW_ESSID_MAX_SIZE - network->ssid_len);
870
871 IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
872 network->ssid, network->ssid_len);
873 break;
874
875 case MFIE_TYPE_RATES:
876#ifdef CONFIG_IEEE80211_DEBUG
877 p = rates_str;
878#endif
879 network->rates_len = min(info_element->len, MAX_RATES_LENGTH);
880 for (i = 0; i < network->rates_len; i++) {
881 network->rates[i] = info_element->data[i];
882#ifdef CONFIG_IEEE80211_DEBUG
883 p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
884#endif
885 if (ieee80211_is_ofdm_rate(info_element->data[i])) {
886 network->flags |= NETWORK_HAS_OFDM;
887 if (info_element->data[i] &
888 IEEE80211_BASIC_RATE_MASK)
889 network->flags &=
890 ~NETWORK_HAS_CCK;
891 }
892 }
893
894 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
895 rates_str, network->rates_len);
896 break;
897
898 case MFIE_TYPE_RATES_EX:
899#ifdef CONFIG_IEEE80211_DEBUG
900 p = rates_str;
901#endif
902 network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH);
903 for (i = 0; i < network->rates_ex_len; i++) {
904 network->rates_ex[i] = info_element->data[i];
905#ifdef CONFIG_IEEE80211_DEBUG
906 p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
907#endif
908 if (ieee80211_is_ofdm_rate(info_element->data[i])) {
909 network->flags |= NETWORK_HAS_OFDM;
910 if (info_element->data[i] &
911 IEEE80211_BASIC_RATE_MASK)
912 network->flags &=
913 ~NETWORK_HAS_CCK;
914 }
915 }
916
917 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
918 rates_str, network->rates_ex_len);
919 break;
920
921 case MFIE_TYPE_DS_SET:
922 IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
923 info_element->data[0]);
924 if (stats->freq == IEEE80211_24GHZ_BAND)
925 network->channel = info_element->data[0];
926 break;
927
928 case MFIE_TYPE_FH_SET:
929 IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
930 break;
931
932 case MFIE_TYPE_CF_SET:
933 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
934 break;
935
936 case MFIE_TYPE_TIM:
937 IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
938 break;
939
940 case MFIE_TYPE_IBSS_SET:
941 IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
942 break;
943
944 case MFIE_TYPE_CHALLENGE:
945 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
946 break;
947
948 case MFIE_TYPE_GENERIC:
949 IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
950 info_element->len);
951 if (info_element->len >= 4 &&
952 info_element->data[0] == 0x00 &&
953 info_element->data[1] == 0x50 &&
954 info_element->data[2] == 0xf2 &&
955 info_element->data[3] == 0x01) {
956 network->wpa_ie_len = min(info_element->len + 2,
957 MAX_WPA_IE_LEN);
958 memcpy(network->wpa_ie, info_element,
959 network->wpa_ie_len);
960 }
961 break;
962
963 case MFIE_TYPE_RSN:
964 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
965 info_element->len);
966 network->rsn_ie_len = min(info_element->len + 2,
967 MAX_WPA_IE_LEN);
968 memcpy(network->rsn_ie, info_element,
969 network->rsn_ie_len);
970 break;
971
972 default:
973 IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
974 info_element->id);
975 break;
976 }
977
978 left -= sizeof(struct ieee80211_info_element_hdr) +
979 info_element->len;
980 info_element = (struct ieee80211_info_element *)
981 &info_element->data[info_element->len];
982 }
983
984 network->mode = 0;
985 if (stats->freq == IEEE80211_52GHZ_BAND)
986 network->mode = IEEE_A;
987 else {
988 if (network->flags & NETWORK_HAS_OFDM)
989 network->mode |= IEEE_G;
990 if (network->flags & NETWORK_HAS_CCK)
991 network->mode |= IEEE_B;
992 }
993
994 if (network->mode == 0) {
995 IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
996 "network.\n",
997 escape_essid(network->ssid,
998 network->ssid_len),
999 MAC_ARG(network->bssid));
1000 return 1;
1001 }
1002
1003 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1004 network->flags |= NETWORK_EMPTY_ESSID;
1005
1006 memcpy(&network->stats, stats, sizeof(network->stats));
1007
1008 return 0;
1009}
1010
1011static inline int is_same_network(struct ieee80211_network *src,
1012 struct ieee80211_network *dst)
1013{
1014 /* A network is only a duplicate if the channel, BSSID, and ESSID
1015 * all match. We treat all <hidden> with the same BSSID and channel
1016 * as one network */
1017 return ((src->ssid_len == dst->ssid_len) &&
1018 (src->channel == dst->channel) &&
1019 !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
1020 !memcmp(src->ssid, dst->ssid, src->ssid_len));
1021}
1022
1023static inline void update_network(struct ieee80211_network *dst,
1024 struct ieee80211_network *src)
1025{
1026 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1027 dst->capability = src->capability;
1028 memcpy(dst->rates, src->rates, src->rates_len);
1029 dst->rates_len = src->rates_len;
1030 memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
1031 dst->rates_ex_len = src->rates_ex_len;
1032
1033 dst->mode = src->mode;
1034 dst->flags = src->flags;
1035 dst->time_stamp[0] = src->time_stamp[0];
1036 dst->time_stamp[1] = src->time_stamp[1];
1037
1038 dst->beacon_interval = src->beacon_interval;
1039 dst->listen_interval = src->listen_interval;
1040 dst->atim_window = src->atim_window;
1041
1042 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1043 dst->wpa_ie_len = src->wpa_ie_len;
1044 memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
1045 dst->rsn_ie_len = src->rsn_ie_len;
1046
1047 dst->last_scanned = jiffies;
1048 /* dst->last_associate is not overwritten */
1049}
1050
1051static inline void ieee80211_process_probe_response(
1052 struct ieee80211_device *ieee,
1053 struct ieee80211_probe_response *beacon,
1054 struct ieee80211_rx_stats *stats)
1055{
1056 struct ieee80211_network network;
1057 struct ieee80211_network *target;
1058 struct ieee80211_network *oldest = NULL;
1059#ifdef CONFIG_IEEE80211_DEBUG
1060 struct ieee80211_info_element *info_element = &beacon->info_element;
1061#endif
1062 unsigned long flags;
1063
1064 IEEE80211_DEBUG_SCAN(
1065 "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
1066 escape_essid(info_element->data, info_element->len),
1067 MAC_ARG(beacon->header.addr3),
1068 (beacon->capability & (1<<0xf)) ? '1' : '0',
1069 (beacon->capability & (1<<0xe)) ? '1' : '0',
1070 (beacon->capability & (1<<0xd)) ? '1' : '0',
1071 (beacon->capability & (1<<0xc)) ? '1' : '0',
1072 (beacon->capability & (1<<0xb)) ? '1' : '0',
1073 (beacon->capability & (1<<0xa)) ? '1' : '0',
1074 (beacon->capability & (1<<0x9)) ? '1' : '0',
1075 (beacon->capability & (1<<0x8)) ? '1' : '0',
1076 (beacon->capability & (1<<0x7)) ? '1' : '0',
1077 (beacon->capability & (1<<0x6)) ? '1' : '0',
1078 (beacon->capability & (1<<0x5)) ? '1' : '0',
1079 (beacon->capability & (1<<0x4)) ? '1' : '0',
1080 (beacon->capability & (1<<0x3)) ? '1' : '0',
1081 (beacon->capability & (1<<0x2)) ? '1' : '0',
1082 (beacon->capability & (1<<0x1)) ? '1' : '0',
1083 (beacon->capability & (1<<0x0)) ? '1' : '0');
1084
1085 if (ieee80211_network_init(ieee, beacon, &network, stats)) {
1086 IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
1087 escape_essid(info_element->data,
1088 info_element->len),
1089 MAC_ARG(beacon->header.addr3),
1090 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1091 IEEE80211_STYPE_PROBE_RESP ?
1092 "PROBE RESPONSE" : "BEACON");
1093 return;
1094 }
1095
1096 /* The network parsed correctly -- so now we scan our known networks
1097 * to see if we can find it in our list.
1098 *
1099 * NOTE: This search is definitely not optimized. Once its doing
1100 * the "right thing" we'll optimize it for efficiency if
1101 * necessary */
1102
1103 /* Search for this entry in the list and update it if it is
1104 * already there. */
1105
1106 spin_lock_irqsave(&ieee->lock, flags);
1107
1108 list_for_each_entry(target, &ieee->network_list, list) {
1109 if (is_same_network(target, &network))
1110 break;
1111
1112 if ((oldest == NULL) ||
1113 (target->last_scanned < oldest->last_scanned))
1114 oldest = target;
1115 }
1116
1117 /* If we didn't find a match, then get a new network slot to initialize
1118 * with this beacon's information */
1119 if (&target->list == &ieee->network_list) {
1120 if (list_empty(&ieee->network_free_list)) {
1121 /* If there are no more slots, expire the oldest */
1122 list_del(&oldest->list);
1123 target = oldest;
1124 IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
1125 "network list.\n",
1126 escape_essid(target->ssid,
1127 target->ssid_len),
1128 MAC_ARG(target->bssid));
1129 } else {
1130 /* Otherwise just pull from the free list */
1131 target = list_entry(ieee->network_free_list.next,
1132 struct ieee80211_network, list);
1133 list_del(ieee->network_free_list.next);
1134 }
1135
1136
1137#ifdef CONFIG_IEEE80211_DEBUG
1138 IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
1139 escape_essid(network.ssid,
1140 network.ssid_len),
1141 MAC_ARG(network.bssid),
1142 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1143 IEEE80211_STYPE_PROBE_RESP ?
1144 "PROBE RESPONSE" : "BEACON");
1145#endif
1146 memcpy(target, &network, sizeof(*target));
1147 list_add_tail(&target->list, &ieee->network_list);
1148 } else {
1149 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
1150 escape_essid(target->ssid,
1151 target->ssid_len),
1152 MAC_ARG(target->bssid),
1153 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1154 IEEE80211_STYPE_PROBE_RESP ?
1155 "PROBE RESPONSE" : "BEACON");
1156 update_network(target, &network);
1157 }
1158
1159 spin_unlock_irqrestore(&ieee->lock, flags);
1160}
1161
1162void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1163 struct ieee80211_hdr *header,
1164 struct ieee80211_rx_stats *stats)
1165{
1166 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1167 case IEEE80211_STYPE_ASSOC_RESP:
1168 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
1169 WLAN_FC_GET_STYPE(header->frame_ctl));
1170 break;
1171
1172 case IEEE80211_STYPE_REASSOC_RESP:
1173 IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
1174 WLAN_FC_GET_STYPE(header->frame_ctl));
1175 break;
1176
1177 case IEEE80211_STYPE_PROBE_RESP:
1178 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1179 WLAN_FC_GET_STYPE(header->frame_ctl));
1180 IEEE80211_DEBUG_SCAN("Probe response\n");
1181 ieee80211_process_probe_response(
1182 ieee, (struct ieee80211_probe_response *)header, stats);
1183 break;
1184
1185 case IEEE80211_STYPE_BEACON:
1186 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1187 WLAN_FC_GET_STYPE(header->frame_ctl));
1188 IEEE80211_DEBUG_SCAN("Beacon\n");
1189 ieee80211_process_probe_response(
1190 ieee, (struct ieee80211_probe_response *)header, stats);
1191 break;
1192
1193 default:
1194 IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
1195 WLAN_FC_GET_STYPE(header->frame_ctl));
1196 IEEE80211_WARNING("%s: Unknown management packet: %d\n",
1197 ieee->dev->name,
1198 WLAN_FC_GET_STYPE(header->frame_ctl));
1199 break;
1200 }
1201}
1202
1203
1204EXPORT_SYMBOL(ieee80211_rx_mgt);
1205EXPORT_SYMBOL(ieee80211_rx);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
new file mode 100644
index 000000000000..d1049edcd14d
--- /dev/null
+++ b/net/ieee80211/ieee80211_tx.c
@@ -0,0 +1,447 @@
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/proc_fs.h>
37#include <linux/skbuff.h>
38#include <linux/slab.h>
39#include <linux/tcp.h>
40#include <linux/types.h>
41#include <linux/version.h>
42#include <linux/wireless.h>
43#include <linux/etherdevice.h>
44#include <asm/uaccess.h>
45
46#include <net/ieee80211.h>
47
48
49/*
50
51
52802.11 Data Frame
53
54 ,-------------------------------------------------------------------.
55Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
56 |------|------|---------|---------|---------|------|---------|------|
57Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
58 | | tion | (BSSID) | | | ence | data | |
59 `--------------------------------------------------| |------'
60Total: 28 non-data bytes `----.----'
61 |
62 .- 'Frame data' expands to <---------------------------'
63 |
64 V
65 ,---------------------------------------------------.
66Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
67 |------|------|---------|----------|------|---------|
68Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
69 | DSAP | SSAP | | | | Packet |
70 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
71 `-----------------------------------------| |
72Total: 8 non-data bytes `----.----'
73 |
74 .- 'IP Packet' expands, if WEP enabled, to <--'
75 |
76 V
77 ,-----------------------.
78Bytes | 4 | 0-2296 | 4 |
79 |-----|-----------|-----|
80Desc. | IV | Encrypted | ICV |
81 | | IP Packet | |
82 `-----------------------'
83Total: 8 non-data bytes
84
85
86802.3 Ethernet Data Frame
87
88 ,-----------------------------------------.
89Bytes | 6 | 6 | 2 | Variable | 4 |
90 |-------|-------|------|-----------|------|
91Desc. | Dest. | Source| Type | IP Packet | fcs |
92 | MAC | MAC | | | |
93 `-----------------------------------------'
94Total: 18 non-data bytes
95
96In the event that fragmentation is required, the incoming payload is split into
97N parts of size ieee->fts. The first fragment contains the SNAP header and the
98remaining packets are just data.
99
100If encryption is enabled, each fragment payload size is reduced by enough space
101to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
102So if you have 1500 bytes of payload with ieee->fts set to 500 without
103encryption it will take 3 frames. With WEP it will take 4 frames as the
104payload of each frame is reduced to 492 bytes.
105
106* SKB visualization
107*
108* ,- skb->data
109* |
110* | ETHERNET HEADER ,-<-- PAYLOAD
111* | | 14 bytes from skb->data
112* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
113* | | | |
114* |,-Dest.--. ,--Src.---. | | |
115* | 6 bytes| | 6 bytes | | | |
116* v | | | | | |
117* 0 | v 1 | v | v 2
118* 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
119* ^ | ^ | ^ |
120* | | | | | |
121* | | | | `T' <---- 2 bytes for Type
122* | | | |
123* | | '---SNAP--' <-------- 6 bytes for SNAP
124* | |
125* `-IV--' <-------------------- 4 bytes for IV (WEP)
126*
127* SNAP HEADER
128*
129*/
130
131static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
132static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
133
134static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
135{
136 struct ieee80211_snap_hdr *snap;
137 u8 *oui;
138
139 snap = (struct ieee80211_snap_hdr *)data;
140 snap->dsap = 0xaa;
141 snap->ssap = 0xaa;
142 snap->ctrl = 0x03;
143
144 if (h_proto == 0x8137 || h_proto == 0x80f3)
145 oui = P802_1H_OUI;
146 else
147 oui = RFC1042_OUI;
148 snap->oui[0] = oui[0];
149 snap->oui[1] = oui[1];
150 snap->oui[2] = oui[2];
151
152 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
153
154 return SNAP_SIZE + sizeof(u16);
155}
156
157static inline int ieee80211_encrypt_fragment(
158 struct ieee80211_device *ieee,
159 struct sk_buff *frag,
160 int hdr_len)
161{
162 struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
163 int res;
164
165#ifdef CONFIG_IEEE80211_CRYPT_TKIP
166 struct ieee80211_hdr *header;
167
168 if (ieee->tkip_countermeasures &&
169 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
170 header = (struct ieee80211_hdr *) frag->data;
171 if (net_ratelimit()) {
172 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
173 "TX packet to " MAC_FMT "\n",
174 ieee->dev->name, MAC_ARG(header->addr1));
175 }
176 return -1;
177 }
178#endif
179 /* To encrypt, frame format is:
180 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
181
182 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
183 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
184 * call both MSDU and MPDU encryption functions from here. */
185 atomic_inc(&crypt->refcnt);
186 res = 0;
187 if (crypt->ops->encrypt_msdu)
188 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
189 if (res == 0 && crypt->ops->encrypt_mpdu)
190 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
191
192 atomic_dec(&crypt->refcnt);
193 if (res < 0) {
194 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
195 ieee->dev->name, frag->len);
196 ieee->ieee_stats.tx_discards++;
197 return -1;
198 }
199
200 return 0;
201}
202
203
204void ieee80211_txb_free(struct ieee80211_txb *txb) {
205 int i;
206 if (unlikely(!txb))
207 return;
208 for (i = 0; i < txb->nr_frags; i++)
209 if (txb->fragments[i])
210 dev_kfree_skb_any(txb->fragments[i]);
211 kfree(txb);
212}
213
214static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
215 int gfp_mask)
216{
217 struct ieee80211_txb *txb;
218 int i;
219 txb = kmalloc(
220 sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
221 gfp_mask);
222 if (!txb)
223 return NULL;
224
225 memset(txb, 0, sizeof(struct ieee80211_txb));
226 txb->nr_frags = nr_frags;
227 txb->frag_size = txb_size;
228
229 for (i = 0; i < nr_frags; i++) {
230 txb->fragments[i] = dev_alloc_skb(txb_size);
231 if (unlikely(!txb->fragments[i])) {
232 i--;
233 break;
234 }
235 }
236 if (unlikely(i != nr_frags)) {
237 while (i >= 0)
238 dev_kfree_skb_any(txb->fragments[i--]);
239 kfree(txb);
240 return NULL;
241 }
242 return txb;
243}
244
245/* SKBs are added to the ieee->tx_queue. */
246int ieee80211_xmit(struct sk_buff *skb,
247 struct net_device *dev)
248{
249 struct ieee80211_device *ieee = netdev_priv(dev);
250 struct ieee80211_txb *txb = NULL;
251 struct ieee80211_hdr *frag_hdr;
252 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
253 unsigned long flags;
254 struct net_device_stats *stats = &ieee->stats;
255 int ether_type, encrypt;
256 int bytes, fc, hdr_len;
257 struct sk_buff *skb_frag;
258 struct ieee80211_hdr header = { /* Ensure zero initialized */
259 .duration_id = 0,
260 .seq_ctl = 0
261 };
262 u8 dest[ETH_ALEN], src[ETH_ALEN];
263
264 struct ieee80211_crypt_data* crypt;
265
266 spin_lock_irqsave(&ieee->lock, flags);
267
268 /* If there is no driver handler to take the TXB, dont' bother
269 * creating it... */
270 if (!ieee->hard_start_xmit) {
271 printk(KERN_WARNING "%s: No xmit handler.\n",
272 ieee->dev->name);
273 goto success;
274 }
275
276 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
277 printk(KERN_WARNING "%s: skb too small (%d).\n",
278 ieee->dev->name, skb->len);
279 goto success;
280 }
281
282 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
283
284 crypt = ieee->crypt[ieee->tx_keyidx];
285
286 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
287 ieee->host_encrypt && crypt && crypt->ops;
288
289 if (!encrypt && ieee->ieee802_1x &&
290 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
291 stats->tx_dropped++;
292 goto success;
293 }
294
295#ifdef CONFIG_IEEE80211_DEBUG
296 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
297 struct eapol *eap = (struct eapol *)(skb->data +
298 sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
299 IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
300 eap_get_type(eap->type));
301 }
302#endif
303
304 /* Save source and destination addresses */
305 memcpy(&dest, skb->data, ETH_ALEN);
306 memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
307
308 /* Advance the SKB to the start of the payload */
309 skb_pull(skb, sizeof(struct ethhdr));
310
311 /* Determine total amount of storage required for TXB packets */
312 bytes = skb->len + SNAP_SIZE + sizeof(u16);
313
314 if (encrypt)
315 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
316 IEEE80211_FCTL_WEP;
317 else
318 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
319
320 if (ieee->iw_mode == IW_MODE_INFRA) {
321 fc |= IEEE80211_FCTL_TODS;
322 /* To DS: Addr1 = BSSID, Addr2 = SA,
323 Addr3 = DA */
324 memcpy(&header.addr1, ieee->bssid, ETH_ALEN);
325 memcpy(&header.addr2, &src, ETH_ALEN);
326 memcpy(&header.addr3, &dest, ETH_ALEN);
327 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
328 /* not From/To DS: Addr1 = DA, Addr2 = SA,
329 Addr3 = BSSID */
330 memcpy(&header.addr1, dest, ETH_ALEN);
331 memcpy(&header.addr2, src, ETH_ALEN);
332 memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
333 }
334 header.frame_ctl = cpu_to_le16(fc);
335 hdr_len = IEEE80211_3ADDR_LEN;
336
337 /* Determine fragmentation size based on destination (multicast
338 * and broadcast are not fragmented) */
339 if (is_multicast_ether_addr(dest) ||
340 is_broadcast_ether_addr(dest))
341 frag_size = MAX_FRAG_THRESHOLD;
342 else
343 frag_size = ieee->fts;
344
345 /* Determine amount of payload per fragment. Regardless of if
346 * this stack is providing the full 802.11 header, one will
347 * eventually be affixed to this fragment -- so we must account for
348 * it when determining the amount of payload space. */
349 bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
350 if (ieee->config &
351 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
352 bytes_per_frag -= IEEE80211_FCS_LEN;
353
354 /* Each fragment may need to have room for encryptiong pre/postfix */
355 if (encrypt)
356 bytes_per_frag -= crypt->ops->extra_prefix_len +
357 crypt->ops->extra_postfix_len;
358
359 /* Number of fragments is the total bytes_per_frag /
360 * payload_per_fragment */
361 nr_frags = bytes / bytes_per_frag;
362 bytes_last_frag = bytes % bytes_per_frag;
363 if (bytes_last_frag)
364 nr_frags++;
365 else
366 bytes_last_frag = bytes_per_frag;
367
368 /* When we allocate the TXB we allocate enough space for the reserve
369 * and full fragment bytes (bytes_per_frag doesn't include prefix,
370 * postfix, header, FCS, etc.) */
371 txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
372 if (unlikely(!txb)) {
373 printk(KERN_WARNING "%s: Could not allocate TXB\n",
374 ieee->dev->name);
375 goto failed;
376 }
377 txb->encrypted = encrypt;
378 txb->payload_size = bytes;
379
380 for (i = 0; i < nr_frags; i++) {
381 skb_frag = txb->fragments[i];
382
383 if (encrypt)
384 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
385
386 frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
387 memcpy(frag_hdr, &header, hdr_len);
388
389 /* If this is not the last fragment, then add the MOREFRAGS
390 * bit to the frame control */
391 if (i != nr_frags - 1) {
392 frag_hdr->frame_ctl = cpu_to_le16(
393 fc | IEEE80211_FCTL_MOREFRAGS);
394 bytes = bytes_per_frag;
395 } else {
396 /* The last fragment takes the remaining length */
397 bytes = bytes_last_frag;
398 }
399
400 /* Put a SNAP header on the first fragment */
401 if (i == 0) {
402 ieee80211_put_snap(
403 skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
404 ether_type);
405 bytes -= SNAP_SIZE + sizeof(u16);
406 }
407
408 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
409
410 /* Advance the SKB... */
411 skb_pull(skb, bytes);
412
413 /* Encryption routine will move the header forward in order
414 * to insert the IV between the header and the payload */
415 if (encrypt)
416 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
417 if (ieee->config &
418 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
419 skb_put(skb_frag, 4);
420 }
421
422
423 success:
424 spin_unlock_irqrestore(&ieee->lock, flags);
425
426 dev_kfree_skb_any(skb);
427
428 if (txb) {
429 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
430 stats->tx_packets++;
431 stats->tx_bytes += txb->payload_size;
432 return 0;
433 }
434 ieee80211_txb_free(txb);
435 }
436
437 return 0;
438
439 failed:
440 spin_unlock_irqrestore(&ieee->lock, flags);
441 netif_stop_queue(dev);
442 stats->tx_errors++;
443 return 1;
444
445}
446
447EXPORT_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);