[PATCH] wireless/airo: fix setting TX key index plus key in ENCODEEXT
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ieee80211 / ieee80211_module.c
CommitLineData
b453872c
JG
1/*******************************************************************************
2
ebeaddcc 3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
b453872c
JG
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31*******************************************************************************/
32
33#include <linux/compiler.h>
34#include <linux/config.h>
35#include <linux/errno.h>
36#include <linux/if_arp.h>
37#include <linux/in6.h>
38#include <linux/in.h>
39#include <linux/ip.h>
40#include <linux/kernel.h>
41#include <linux/module.h>
42#include <linux/netdevice.h>
b453872c
JG
43#include <linux/proc_fs.h>
44#include <linux/skbuff.h>
45#include <linux/slab.h>
46#include <linux/tcp.h>
47#include <linux/types.h>
b453872c
JG
48#include <linux/wireless.h>
49#include <linux/etherdevice.h>
50#include <asm/uaccess.h>
51#include <net/arp.h>
52
53#include <net/ieee80211.h>
54
31696160
JK
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);
b453872c
JG
63MODULE_LICENSE("GPL");
64
858119e1 65static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
b453872c
JG
66{
67 if (ieee->networks)
68 return 0;
69
0edd5b44
JG
70 ieee->networks =
71 kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
72 GFP_KERNEL);
b453872c
JG
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 memset(ieee->networks, 0,
80 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
81
82 return 0;
83}
84
15f38598
ZY
85void ieee80211_network_reset(struct ieee80211_network *network)
86{
87 if (!network)
88 return;
89
90 if (network->ibss_dfs) {
91 kfree(network->ibss_dfs);
92 network->ibss_dfs = NULL;
93 }
94}
95
b453872c
JG
96static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
97{
15f38598
ZY
98 int i;
99
b453872c
JG
100 if (!ieee->networks)
101 return;
15f38598
ZY
102
103 for (i = 0; i < MAX_NETWORK_COUNT; i++)
104 if (ieee->networks[i].ibss_dfs)
105 kfree(ieee->networks[i].ibss_dfs);
106
b453872c
JG
107 kfree(ieee->networks);
108 ieee->networks = NULL;
109}
110
858119e1 111static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
b453872c
JG
112{
113 int i;
114
115 INIT_LIST_HEAD(&ieee->network_free_list);
116 INIT_LIST_HEAD(&ieee->network_list);
117 for (i = 0; i < MAX_NETWORK_COUNT; i++)
0edd5b44
JG
118 list_add_tail(&ieee->networks[i].list,
119 &ieee->network_free_list);
b453872c
JG
120}
121
b453872c
JG
122struct net_device *alloc_ieee80211(int sizeof_priv)
123{
124 struct ieee80211_device *ieee;
125 struct net_device *dev;
126 int err;
127
128 IEEE80211_DEBUG_INFO("Initializing...\n");
129
130 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
131 if (!dev) {
132 IEEE80211_ERROR("Unable to network device.\n");
133 goto failed;
134 }
135 ieee = netdev_priv(dev);
136 dev->hard_start_xmit = ieee80211_xmit;
137
138 ieee->dev = dev;
139
140 err = ieee80211_networks_allocate(ieee);
141 if (err) {
0edd5b44 142 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
b453872c
JG
143 goto failed;
144 }
145 ieee80211_networks_initialize(ieee);
146
147 /* Default fragmentation threshold is maximum payload size */
148 ieee->fts = DEFAULT_FTS;
3cdd00c5 149 ieee->rts = DEFAULT_FTS;
b453872c
JG
150 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
151 ieee->open_wep = 1;
152
153 /* Default to enabling full open WEP with host based encrypt/decrypt */
154 ieee->host_encrypt = 1;
155 ieee->host_decrypt = 1;
ccd0fda3
JK
156 ieee->host_mc_decrypt = 1;
157
1264fc04
JK
158 /* Host fragementation in Open mode. Default is enabled.
159 * Note: host fragmentation is always enabled if host encryption
160 * is enabled. For cards can do hardware encryption, they must do
161 * hardware fragmentation as well. So we don't need a variable
162 * like host_enc_frag. */
163 ieee->host_open_frag = 1;
0edd5b44 164 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
b453872c
JG
165
166 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
167 init_timer(&ieee->crypt_deinit_timer);
168 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
169 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
0ad0c3c6 170 ieee->crypt_quiesced = 0;
b453872c
JG
171
172 spin_lock_init(&ieee->lock);
173
0edd5b44 174 ieee->wpa_enabled = 0;
0edd5b44
JG
175 ieee->drop_unencrypted = 0;
176 ieee->privacy_invoked = 0;
b453872c
JG
177
178 return dev;
179
0edd5b44 180 failed:
b453872c
JG
181 if (dev)
182 free_netdev(dev);
183 return NULL;
184}
185
b453872c
JG
186void free_ieee80211(struct net_device *dev)
187{
188 struct ieee80211_device *ieee = netdev_priv(dev);
189
190 int i;
191
0ad0c3c6 192 ieee80211_crypt_quiescing(ieee);
b453872c
JG
193 del_timer_sync(&ieee->crypt_deinit_timer);
194 ieee80211_crypt_deinit_entries(ieee, 1);
195
196 for (i = 0; i < WEP_KEYS; i++) {
197 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
198 if (crypt) {
199 if (crypt->ops) {
200 crypt->ops->deinit(crypt->priv);
201 module_put(crypt->ops->owner);
202 }
203 kfree(crypt);
204 ieee->crypt[i] = NULL;
205 }
206 }
207
208 ieee80211_networks_free(ieee);
209 free_netdev(dev);
210}
211
212#ifdef CONFIG_IEEE80211_DEBUG
213
214static int debug = 0;
215u32 ieee80211_debug_level = 0;
216struct proc_dir_entry *ieee80211_proc = NULL;
217
218static int show_debug_level(char *page, char **start, off_t offset,
219 int count, int *eof, void *data)
220{
221 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
222}
223
0edd5b44 224static int store_debug_level(struct file *file, const char __user * buffer,
b453872c
JG
225 unsigned long count, void *data)
226{
262d8e46
JK
227 char buf[] = "0x00000000\n";
228 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
b453872c
JG
229 unsigned long val;
230
262d8e46 231 if (copy_from_user(buf, buffer, len))
b453872c 232 return count;
262d8e46
JK
233 buf[len] = 0;
234 if (sscanf(buf, "%li", &val) != 1)
b453872c
JG
235 printk(KERN_INFO DRV_NAME
236 ": %s is not in hex or decimal form.\n", buf);
237 else
238 ieee80211_debug_level = val;
239
262d8e46 240 return strnlen(buf, len);
b453872c 241}
31696160 242#endif /* CONFIG_IEEE80211_DEBUG */
b453872c
JG
243
244static int __init ieee80211_init(void)
245{
31696160 246#ifdef CONFIG_IEEE80211_DEBUG
b453872c
JG
247 struct proc_dir_entry *e;
248
249 ieee80211_debug_level = debug;
66600221 250 ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
b453872c
JG
251 if (ieee80211_proc == NULL) {
252 IEEE80211_ERROR("Unable to create " DRV_NAME
253 " proc directory\n");
254 return -EIO;
255 }
256 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
257 ieee80211_proc);
258 if (!e) {
259 remove_proc_entry(DRV_NAME, proc_net);
260 ieee80211_proc = NULL;
261 return -EIO;
262 }
263 e->read_proc = show_debug_level;
264 e->write_proc = store_debug_level;
265 e->data = NULL;
31696160
JK
266#endif /* CONFIG_IEEE80211_DEBUG */
267
268 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
269 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
b453872c
JG
270
271 return 0;
272}
273
274static void __exit ieee80211_exit(void)
275{
31696160 276#ifdef CONFIG_IEEE80211_DEBUG
b453872c
JG
277 if (ieee80211_proc) {
278 remove_proc_entry("debug_level", ieee80211_proc);
279 remove_proc_entry(DRV_NAME, proc_net);
280 ieee80211_proc = NULL;
281 }
31696160 282#endif /* CONFIG_IEEE80211_DEBUG */
b453872c
JG
283}
284
31696160 285#ifdef CONFIG_IEEE80211_DEBUG
b453872c
JG
286#include <linux/moduleparam.h>
287module_param(debug, int, 0444);
288MODULE_PARM_DESC(debug, "debug output mask");
31696160 289#endif /* CONFIG_IEEE80211_DEBUG */
b453872c 290
b453872c
JG
291module_exit(ieee80211_exit);
292module_init(ieee80211_init);
b453872c 293
0edd5b44
JG
294const char *escape_essid(const char *essid, u8 essid_len)
295{
e88187ee
JB
296 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
297 const char *s = essid;
298 char *d = escaped;
299
300 if (ieee80211_is_empty_essid(essid, essid_len)) {
301 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
302 return escaped;
303 }
304
0edd5b44 305 essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
e88187ee
JB
306 while (essid_len--) {
307 if (*s == '\0') {
308 *d++ = '\\';
309 *d++ = '0';
310 s++;
311 } else {
312 *d++ = *s++;
313 }
314 }
315 *d = '\0';
316 return escaped;
317}
318
b453872c
JG
319EXPORT_SYMBOL(alloc_ieee80211);
320EXPORT_SYMBOL(free_ieee80211);
e88187ee 321EXPORT_SYMBOL(escape_essid);