This commit was generated by cvs2svn to compensate for changes in r925,
[linux-2.6.git] / drivers / net / wireless / ieee80211 / ieee80211_module.c
1 /*******************************************************************************
2   
3   Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5   Portions of this file are based on the WEP enablement code provided by the
6   Host AP project hostap-drivers v0.1.3
7   Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8   <jkmaline@cc.hut.fi>
9   Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10   
11   This program is free software; you can redistribute it and/or modify it 
12   under the terms of version 2 of the GNU General Public License as 
13   published by the Free Software Foundation.
14
15   This program is distributed in the hope that it will be useful, but WITHOUT 
16   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
17   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
18   more details.
19   
20   You should have received a copy of the GNU General Public License along with
21   this program; if not, write to the Free Software Foundation, Inc., 59 
22   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23   
24   The full GNU General Public License is included in this distribution in the
25   file called LICENSE.
26   
27   Contact Information:
28   James P. Ketrenos <ipw2100-admin@linux.intel.com>
29   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31 *******************************************************************************/
32
33 #include <linux/compiler.h>
34 #include <linux/config.h>
35 #include <linux/errno.h>
36 #include <linux/if_arp.h>
37 #include <linux/in6.h>
38 #include <linux/in.h>
39 #include <linux/ip.h>
40 #include <linux/kernel.h>
41 #include <linux/module.h>
42 #include <linux/netdevice.h>
43 #include <linux/pci.h>
44 #include <linux/proc_fs.h>
45 #include <linux/skbuff.h>
46 #include <linux/slab.h>
47 #include <linux/tcp.h>
48 #include <linux/types.h>
49 #include <linux/version.h>
50 #include <linux/wireless.h>
51 #include <linux/etherdevice.h>
52 #include <asm/uaccess.h>
53
54 #include "ieee80211.h"
55
56 MODULE_DESCRIPTION("802.11 data/management/control stack");
57 MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
58 MODULE_LICENSE("GPL");
59
60 #define DRV_NAME "ieee80211"
61
62 static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
63 {
64         if (ieee->networks)
65                 return 0;
66
67         ieee->networks = kmalloc(
68                 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
69                 GFP_KERNEL);
70         if (!ieee->networks) {
71                 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
72                        ieee->dev->name);
73                 return -ENOMEM;
74         }
75
76         memset(ieee->networks, 0, 
77                MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
78
79         return 0;
80 }
81
82 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
83 {
84         if (!ieee->networks)
85                 return;
86         kfree(ieee->networks);
87         ieee->networks = NULL;
88 }
89
90 static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
91 {
92         int i;
93
94         INIT_LIST_HEAD(&ieee->network_free_list);
95         INIT_LIST_HEAD(&ieee->network_list);
96         for (i = 0; i < MAX_NETWORK_COUNT; i++) 
97                 list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
98 }
99
100 struct ieee80211_device *ieee80211_alloc(struct net_device *dev,
101                                          void *priv)
102 {
103         struct ieee80211_device *ieee = kmalloc(
104                 sizeof(struct ieee80211_device), GFP_KERNEL);
105         int err;
106         if (ieee == NULL)
107                 return NULL;
108         memset(ieee, 0, sizeof(*ieee));
109         ieee->dev = dev;
110         ieee->priv = priv;
111
112         err = ieee80211_networks_allocate(ieee);
113         if (err) {
114                 IEEE80211_ERROR("Unable to allocate beacon storage\n");
115                 goto error;
116         }
117         ieee80211_networks_initialize(ieee);
118
119         /* Default fragmentation threshold is maximum payload size */
120         ieee->fts = DEFAULT_FTS;
121         ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
122         ieee->open_wep = 1;
123
124 #ifdef CONFIG_IEEE80211_CRYPT
125         /* Default to enabling full open WEP with host based encrypt/decrypt */
126         ieee->host_encrypt = 1;
127         ieee->host_decrypt = 1;
128
129         INIT_LIST_HEAD(&ieee->crypt_deinit_list);
130         init_timer(&ieee->crypt_deinit_timer);
131         ieee->crypt_deinit_timer.data = (unsigned long)ieee;
132         ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
133 #endif
134
135         spin_lock_init(&ieee->lock);
136
137         return ieee;
138
139  error:
140         if (ieee) 
141                 kfree(ieee);
142         return NULL;
143 }
144
145 void ieee80211_free(struct ieee80211_device *ieee)
146 {
147 #ifdef CONFIG_IEEE80211_CRYPT
148         int i;
149
150         del_timer_sync(&ieee->crypt_deinit_timer);
151         ieee80211_crypt_deinit_entries(ieee, 1);
152
153         for (i = 0; i < WEP_KEYS; i++) {
154                 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
155                 if (crypt) {
156                         if (crypt->ops) {
157                                 crypt->ops->deinit(crypt->priv);
158                                 module_put(crypt->ops->owner);
159                         }
160                         kfree(crypt);
161                         ieee->crypt[i] = NULL;
162                 }
163         }
164 #endif
165         ieee80211_networks_free(ieee);
166         kfree(ieee);
167 }
168
169 #ifdef CONFIG_IEEE80211_DEBUG
170
171 static int debug = 0;
172 u32 ieee80211_debug_level = 0;
173 struct proc_dir_entry *ieee80211_proc = NULL;
174
175 static int show_debug_level(char *page, char **start, off_t offset, 
176                             int count, int *eof, void *data)
177 {
178         return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
179 }
180
181 static int store_debug_level(struct file *file, const char *buffer,
182                              unsigned long count, void *data)
183 {
184         char buf[] = "0x00000000";
185         unsigned long len = min(sizeof(buf) - 1, (u32)count);
186         char *p = (char *)buf;
187         unsigned long val;
188
189         if (copy_from_user(buf, buffer, len)) 
190                 return count;
191         buf[len] = 0;
192         if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
193                 p++;
194                 if (p[0] == 'x' || p[0] == 'X')
195                         p++;
196                 val = simple_strtoul(p, &p, 16);
197         } else
198                 val = simple_strtoul(p, &p, 10);
199         if (p == buf) 
200                 printk(KERN_INFO DRV_NAME 
201                        ": %s is not in hex or decimal form.\n", buf);
202         else
203                 ieee80211_debug_level = val;
204
205         return strnlen(buf, count);
206 }
207
208 static int __init ieee80211_init(void) 
209 {
210         struct proc_dir_entry *e;
211
212         ieee80211_debug_level = debug;
213         ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
214         if (ieee80211_proc == NULL) {
215                 IEEE80211_ERROR("Unable to create " DRV_NAME 
216                                 " proc directory\n");
217                 return -EIO;
218         }
219         e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
220                               ieee80211_proc);
221         if (!e) {
222                 remove_proc_entry(DRV_NAME, proc_net);
223                 ieee80211_proc = NULL;
224                 return -EIO;
225         }
226         e->read_proc = show_debug_level;
227         e->write_proc = store_debug_level;
228         e->data = NULL;
229
230         return 0;
231 }
232
233 static void __exit ieee80211_exit(void)
234 {
235         if (ieee80211_proc) {
236                 remove_proc_entry("debug_level", ieee80211_proc);
237                 remove_proc_entry(DRV_NAME, proc_net);
238                 ieee80211_proc = NULL;
239         }
240 }
241
242 #include <linux/moduleparam.h>
243 module_param(debug, int, 0444);
244 MODULE_PARM_DESC(debug, "debug output mask");
245
246
247 module_exit(ieee80211_exit);
248 module_init(ieee80211_init);
249 #endif
250
251 EXPORT_SYMBOL(ieee80211_alloc);
252 EXPORT_SYMBOL(ieee80211_free);