[PATCH] mutex: some cleanups
[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/config.h>
35 #include <linux/errno.h>
36 #include <linux/if_arp.h>
37 #include <linux/in6.h>
38 #include <linux/in.h>
39 #include <linux/ip.h>
40 #include <linux/kernel.h>
41 #include <linux/module.h>
42 #include <linux/netdevice.h>
43 #include <linux/proc_fs.h>
44 #include <linux/skbuff.h>
45 #include <linux/slab.h>
46 #include <linux/tcp.h>
47 #include <linux/types.h>
48 #include <linux/wireless.h>
49 #include <linux/etherdevice.h>
50 #include <asm/uaccess.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
60 MODULE_VERSION(DRV_VERSION);
61 MODULE_DESCRIPTION(DRV_DESCRIPTION);
62 MODULE_AUTHOR(DRV_COPYRIGHT);
63 MODULE_LICENSE("GPL");
64
65 static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
66 {
67         if (ieee->networks)
68                 return 0;
69
70         ieee->networks =
71             kmalloc(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         memset(ieee->networks, 0,
80                MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
81
82         return 0;
83 }
84
85 void 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
96 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
97 {
98         int i;
99
100         if (!ieee->networks)
101                 return;
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
107         kfree(ieee->networks);
108         ieee->networks = NULL;
109 }
110
111 static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
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++)
118                 list_add_tail(&ieee->networks[i].list,
119                               &ieee->network_free_list);
120 }
121
122 struct 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) {
142                 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
143                 goto failed;
144         }
145         ieee80211_networks_initialize(ieee);
146
147         /* Default fragmentation threshold is maximum payload size */
148         ieee->fts = DEFAULT_FTS;
149         ieee->rts = DEFAULT_FTS;
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;
156         ieee->host_mc_decrypt = 1;
157
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;
164         ieee->ieee802_1x = 1;   /* Default to supporting 802.1x */
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;
170         ieee->crypt_quiesced = 0;
171
172         spin_lock_init(&ieee->lock);
173
174         ieee->wpa_enabled = 0;
175         ieee->drop_unencrypted = 0;
176         ieee->privacy_invoked = 0;
177
178         return dev;
179
180       failed:
181         if (dev)
182                 free_netdev(dev);
183         return NULL;
184 }
185
186 void free_ieee80211(struct net_device *dev)
187 {
188         struct ieee80211_device *ieee = netdev_priv(dev);
189
190         int i;
191
192         ieee80211_crypt_quiescing(ieee);
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
214 static int debug = 0;
215 u32 ieee80211_debug_level = 0;
216 static struct proc_dir_entry *ieee80211_proc = NULL;
217
218 static 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
224 static int store_debug_level(struct file *file, const char __user * buffer,
225                              unsigned long count, void *data)
226 {
227         char buf[] = "0x00000000\n";
228         unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
229         unsigned long val;
230
231         if (copy_from_user(buf, buffer, len))
232                 return count;
233         buf[len] = 0;
234         if (sscanf(buf, "%li", &val) != 1)
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
240         return strnlen(buf, len);
241 }
242 #endif                          /* CONFIG_IEEE80211_DEBUG */
243
244 static int __init ieee80211_init(void)
245 {
246 #ifdef CONFIG_IEEE80211_DEBUG
247         struct proc_dir_entry *e;
248
249         ieee80211_debug_level = debug;
250         ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
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;
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");
270
271         return 0;
272 }
273
274 static void __exit ieee80211_exit(void)
275 {
276 #ifdef CONFIG_IEEE80211_DEBUG
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         }
282 #endif                          /* CONFIG_IEEE80211_DEBUG */
283 }
284
285 #ifdef CONFIG_IEEE80211_DEBUG
286 #include <linux/moduleparam.h>
287 module_param(debug, int, 0444);
288 MODULE_PARM_DESC(debug, "debug output mask");
289 #endif                          /* CONFIG_IEEE80211_DEBUG */
290
291 module_exit(ieee80211_exit);
292 module_init(ieee80211_init);
293
294 const char *escape_essid(const char *essid, u8 essid_len)
295 {
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
305         essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
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
319 EXPORT_SYMBOL(alloc_ieee80211);
320 EXPORT_SYMBOL(free_ieee80211);
321 EXPORT_SYMBOL(escape_essid);