[PATCH] sem2mutex: kcapi.c
[linux-2.6/mini2440.git] / net / ieee80211 / ieee80211_module.c
blob2cb84d84f67136f08dd1c847893ee223ddbc6882
1 /*******************************************************************************
3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
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>
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.
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.
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.
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
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
31 *******************************************************************************/
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>
53 #include <net/ieee80211.h>
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>"
60 MODULE_VERSION(DRV_VERSION);
61 MODULE_DESCRIPTION(DRV_DESCRIPTION);
62 MODULE_AUTHOR(DRV_COPYRIGHT);
63 MODULE_LICENSE("GPL");
65 static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
67 if (ieee->networks)
68 return 0;
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;
79 memset(ieee->networks, 0,
80 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
82 return 0;
85 void ieee80211_network_reset(struct ieee80211_network *network)
87 if (!network)
88 return;
90 if (network->ibss_dfs) {
91 kfree(network->ibss_dfs);
92 network->ibss_dfs = NULL;
96 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
98 int i;
100 if (!ieee->networks)
101 return;
103 for (i = 0; i < MAX_NETWORK_COUNT; i++)
104 if (ieee->networks[i].ibss_dfs)
105 kfree(ieee->networks[i].ibss_dfs);
107 kfree(ieee->networks);
108 ieee->networks = NULL;
111 static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
113 int i;
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);
122 struct net_device *alloc_ieee80211(int sizeof_priv)
124 struct ieee80211_device *ieee;
125 struct net_device *dev;
126 int err;
128 IEEE80211_DEBUG_INFO("Initializing...\n");
130 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
131 if (!dev) {
132 IEEE80211_ERROR("Unable to network device.\n");
133 goto failed;
135 ieee = netdev_priv(dev);
136 dev->hard_start_xmit = ieee80211_xmit;
138 ieee->dev = dev;
140 err = ieee80211_networks_allocate(ieee);
141 if (err) {
142 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
143 goto failed;
145 ieee80211_networks_initialize(ieee);
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;
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;
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 */
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;
172 spin_lock_init(&ieee->lock);
174 ieee->wpa_enabled = 0;
175 ieee->drop_unencrypted = 0;
176 ieee->privacy_invoked = 0;
178 return dev;
180 failed:
181 if (dev)
182 free_netdev(dev);
183 return NULL;
186 void free_ieee80211(struct net_device *dev)
188 struct ieee80211_device *ieee = netdev_priv(dev);
190 int i;
192 ieee80211_crypt_quiescing(ieee);
193 del_timer_sync(&ieee->crypt_deinit_timer);
194 ieee80211_crypt_deinit_entries(ieee, 1);
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);
203 kfree(crypt);
204 ieee->crypt[i] = NULL;
208 ieee80211_networks_free(ieee);
209 free_netdev(dev);
212 #ifdef CONFIG_IEEE80211_DEBUG
214 static int debug = 0;
215 u32 ieee80211_debug_level = 0;
216 static struct proc_dir_entry *ieee80211_proc = NULL;
218 static int show_debug_level(char *page, char **start, off_t offset,
219 int count, int *eof, void *data)
221 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
224 static int store_debug_level(struct file *file, const char __user * buffer,
225 unsigned long count, void *data)
227 char buf[] = "0x00000000\n";
228 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
229 unsigned long val;
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;
240 return strnlen(buf, len);
242 #endif /* CONFIG_IEEE80211_DEBUG */
244 static int __init ieee80211_init(void)
246 #ifdef CONFIG_IEEE80211_DEBUG
247 struct proc_dir_entry *e;
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;
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;
263 e->read_proc = show_debug_level;
264 e->write_proc = store_debug_level;
265 e->data = NULL;
266 #endif /* CONFIG_IEEE80211_DEBUG */
268 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
269 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
271 return 0;
274 static void __exit ieee80211_exit(void)
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;
282 #endif /* CONFIG_IEEE80211_DEBUG */
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 */
291 module_exit(ieee80211_exit);
292 module_init(ieee80211_init);
294 const char *escape_essid(const char *essid, u8 essid_len)
296 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
297 const char *s = essid;
298 char *d = escaped;
300 if (ieee80211_is_empty_essid(essid, essid_len)) {
301 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
302 return escaped;
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++;
315 *d = '\0';
316 return escaped;
319 EXPORT_SYMBOL(alloc_ieee80211);
320 EXPORT_SYMBOL(free_ieee80211);
321 EXPORT_SYMBOL(escape_essid);