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