Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linvil...
[linux-2.6] / net / ieee80211 / ieee80211_module.c
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   <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/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/arp.h>
51
52 #include <net/ieee80211.h>
53
54 #define DRV_DESCRIPTION "802.11 data/management/control stack"
55 #define DRV_NAME        "ieee80211"
56 #define DRV_VERSION     IEEE80211_VERSION
57 #define DRV_COPYRIGHT   "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
58
59 MODULE_VERSION(DRV_VERSION);
60 MODULE_DESCRIPTION(DRV_DESCRIPTION);
61 MODULE_AUTHOR(DRV_COPYRIGHT);
62 MODULE_LICENSE("GPL");
63
64 static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
65 {
66         if (ieee->networks)
67                 return 0;
68
69         ieee->networks =
70             kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
71                     GFP_KERNEL);
72         if (!ieee->networks) {
73                 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
74                        ieee->dev->name);
75                 return -ENOMEM;
76         }
77
78         memset(ieee->networks, 0,
79                MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
80
81         return 0;
82 }
83
84 void ieee80211_network_reset(struct ieee80211_network *network)
85 {
86         if (!network)
87                 return;
88
89         if (network->ibss_dfs) {
90                 kfree(network->ibss_dfs);
91                 network->ibss_dfs = NULL;
92         }
93 }
94
95 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
96 {
97         int i;
98
99         if (!ieee->networks)
100                 return;
101
102         for (i = 0; i < MAX_NETWORK_COUNT; i++)
103                 if (ieee->networks[i].ibss_dfs)
104                         kfree(ieee->networks[i].ibss_dfs);
105
106         kfree(ieee->networks);
107         ieee->networks = NULL;
108 }
109
110 static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
111 {
112         int i;
113
114         INIT_LIST_HEAD(&ieee->network_free_list);
115         INIT_LIST_HEAD(&ieee->network_list);
116         for (i = 0; i < MAX_NETWORK_COUNT; i++)
117                 list_add_tail(&ieee->networks[i].list,
118                               &ieee->network_free_list);
119 }
120
121 struct net_device *alloc_ieee80211(int sizeof_priv)
122 {
123         struct ieee80211_device *ieee;
124         struct net_device *dev;
125         int err;
126
127         IEEE80211_DEBUG_INFO("Initializing...\n");
128
129         dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
130         if (!dev) {
131                 IEEE80211_ERROR("Unable to network device.\n");
132                 goto failed;
133         }
134         ieee = netdev_priv(dev);
135         dev->hard_start_xmit = ieee80211_xmit;
136
137         ieee->dev = dev;
138
139         err = ieee80211_networks_allocate(ieee);
140         if (err) {
141                 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
142                 goto failed;
143         }
144         ieee80211_networks_initialize(ieee);
145
146         /* Default fragmentation threshold is maximum payload size */
147         ieee->fts = DEFAULT_FTS;
148         ieee->rts = DEFAULT_FTS;
149         ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
150         ieee->open_wep = 1;
151
152         /* Default to enabling full open WEP with host based encrypt/decrypt */
153         ieee->host_encrypt = 1;
154         ieee->host_decrypt = 1;
155         ieee->host_mc_decrypt = 1;
156
157         /* Host fragementation in Open mode. Default is enabled.
158          * Note: host fragmentation is always enabled if host encryption
159          * is enabled. For cards can do hardware encryption, they must do
160          * hardware fragmentation as well. So we don't need a variable
161          * like host_enc_frag. */
162         ieee->host_open_frag = 1;
163         ieee->ieee802_1x = 1;   /* Default to supporting 802.1x */
164
165         INIT_LIST_HEAD(&ieee->crypt_deinit_list);
166         init_timer(&ieee->crypt_deinit_timer);
167         ieee->crypt_deinit_timer.data = (unsigned long)ieee;
168         ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
169         ieee->crypt_quiesced = 0;
170
171         spin_lock_init(&ieee->lock);
172
173         ieee->wpa_enabled = 0;
174         ieee->drop_unencrypted = 0;
175         ieee->privacy_invoked = 0;
176
177         return dev;
178
179       failed:
180         if (dev)
181                 free_netdev(dev);
182         return NULL;
183 }
184
185 void free_ieee80211(struct net_device *dev)
186 {
187         struct ieee80211_device *ieee = netdev_priv(dev);
188
189         int i;
190
191         ieee80211_crypt_quiescing(ieee);
192         del_timer_sync(&ieee->crypt_deinit_timer);
193         ieee80211_crypt_deinit_entries(ieee, 1);
194
195         for (i = 0; i < WEP_KEYS; i++) {
196                 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
197                 if (crypt) {
198                         if (crypt->ops) {
199                                 crypt->ops->deinit(crypt->priv);
200                                 module_put(crypt->ops->owner);
201                         }
202                         kfree(crypt);
203                         ieee->crypt[i] = NULL;
204                 }
205         }
206
207         ieee80211_networks_free(ieee);
208         free_netdev(dev);
209 }
210
211 #ifdef CONFIG_IEEE80211_DEBUG
212
213 static int debug = 0;
214 u32 ieee80211_debug_level = 0;
215 static struct proc_dir_entry *ieee80211_proc = NULL;
216
217 static int show_debug_level(char *page, char **start, off_t offset,
218                             int count, int *eof, void *data)
219 {
220         return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
221 }
222
223 static int store_debug_level(struct file *file, const char __user * buffer,
224                              unsigned long count, void *data)
225 {
226         char buf[] = "0x00000000\n";
227         unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
228         unsigned long val;
229
230         if (copy_from_user(buf, buffer, len))
231                 return count;
232         buf[len] = 0;
233         if (sscanf(buf, "%li", &val) != 1)
234                 printk(KERN_INFO DRV_NAME
235                        ": %s is not in hex or decimal form.\n", buf);
236         else
237                 ieee80211_debug_level = val;
238
239         return strnlen(buf, len);
240 }
241 #endif                          /* CONFIG_IEEE80211_DEBUG */
242
243 static int __init ieee80211_init(void)
244 {
245 #ifdef CONFIG_IEEE80211_DEBUG
246         struct proc_dir_entry *e;
247
248         ieee80211_debug_level = debug;
249         ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
250         if (ieee80211_proc == NULL) {
251                 IEEE80211_ERROR("Unable to create " DRV_NAME
252                                 " proc directory\n");
253                 return -EIO;
254         }
255         e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
256                               ieee80211_proc);
257         if (!e) {
258                 remove_proc_entry(DRV_NAME, proc_net);
259                 ieee80211_proc = NULL;
260                 return -EIO;
261         }
262         e->read_proc = show_debug_level;
263         e->write_proc = store_debug_level;
264         e->data = NULL;
265 #endif                          /* CONFIG_IEEE80211_DEBUG */
266
267         printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
268         printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
269
270         return 0;
271 }
272
273 static void __exit ieee80211_exit(void)
274 {
275 #ifdef CONFIG_IEEE80211_DEBUG
276         if (ieee80211_proc) {
277                 remove_proc_entry("debug_level", ieee80211_proc);
278                 remove_proc_entry(DRV_NAME, proc_net);
279                 ieee80211_proc = NULL;
280         }
281 #endif                          /* CONFIG_IEEE80211_DEBUG */
282 }
283
284 #ifdef CONFIG_IEEE80211_DEBUG
285 #include <linux/moduleparam.h>
286 module_param(debug, int, 0444);
287 MODULE_PARM_DESC(debug, "debug output mask");
288 #endif                          /* CONFIG_IEEE80211_DEBUG */
289
290 module_exit(ieee80211_exit);
291 module_init(ieee80211_init);
292
293 const char *escape_essid(const char *essid, u8 essid_len)
294 {
295         static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
296         const char *s = essid;
297         char *d = escaped;
298
299         if (ieee80211_is_empty_essid(essid, essid_len)) {
300                 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
301                 return escaped;
302         }
303
304         essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
305         while (essid_len--) {
306                 if (*s == '\0') {
307                         *d++ = '\\';
308                         *d++ = '0';
309                         s++;
310                 } else {
311                         *d++ = *s++;
312                 }
313         }
314         *d = '\0';
315         return escaped;
316 }
317
318 EXPORT_SYMBOL(alloc_ieee80211);
319 EXPORT_SYMBOL(free_ieee80211);
320 EXPORT_SYMBOL(escape_essid);