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