libipw_module.c revision b0a4e7d8a291de63f35b04464de9ab4a83d38a7c
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  <j@w1.fi>
9  Copyright (c) 2002-2003, Jouni Malinen <j@w1.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/net_namespace.h>
51#include <net/arp.h>
52
53#include "libipw.h"
54
55#define DRV_DESCRIPTION "802.11 data/management/control stack"
56#define DRV_NAME        "ieee80211"
57#define DRV_VERSION	LIBIPW_VERSION
58#define DRV_COPYRIGHT   "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
59
60MODULE_VERSION(DRV_VERSION);
61MODULE_DESCRIPTION(DRV_DESCRIPTION);
62MODULE_AUTHOR(DRV_COPYRIGHT);
63MODULE_LICENSE("GPL");
64
65static int libipw_networks_allocate(struct libipw_device *ieee)
66{
67	if (ieee->networks)
68		return 0;
69
70	ieee->networks =
71	    kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_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	return 0;
80}
81
82void libipw_network_reset(struct libipw_network *network)
83{
84	if (!network)
85		return;
86
87	if (network->ibss_dfs) {
88		kfree(network->ibss_dfs);
89		network->ibss_dfs = NULL;
90	}
91}
92
93static inline void libipw_networks_free(struct libipw_device *ieee)
94{
95	int i;
96
97	if (!ieee->networks)
98		return;
99
100	for (i = 0; i < MAX_NETWORK_COUNT; i++)
101		if (ieee->networks[i].ibss_dfs)
102			kfree(ieee->networks[i].ibss_dfs);
103
104	kfree(ieee->networks);
105	ieee->networks = NULL;
106}
107
108void libipw_networks_age(struct libipw_device *ieee,
109                            unsigned long age_secs)
110{
111	struct libipw_network *network = NULL;
112	unsigned long flags;
113	unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
114
115	spin_lock_irqsave(&ieee->lock, flags);
116	list_for_each_entry(network, &ieee->network_list, list) {
117		network->last_scanned -= age_jiffies;
118	}
119	spin_unlock_irqrestore(&ieee->lock, flags);
120}
121EXPORT_SYMBOL(libipw_networks_age);
122
123static void libipw_networks_initialize(struct libipw_device *ieee)
124{
125	int i;
126
127	INIT_LIST_HEAD(&ieee->network_free_list);
128	INIT_LIST_HEAD(&ieee->network_list);
129	for (i = 0; i < MAX_NETWORK_COUNT; i++)
130		list_add_tail(&ieee->networks[i].list,
131			      &ieee->network_free_list);
132}
133
134int libipw_change_mtu(struct net_device *dev, int new_mtu)
135{
136	if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
137		return -EINVAL;
138	dev->mtu = new_mtu;
139	return 0;
140}
141EXPORT_SYMBOL(libipw_change_mtu);
142
143struct net_device *alloc_ieee80211(int sizeof_priv)
144{
145	struct libipw_device *ieee;
146	struct net_device *dev;
147	int err;
148
149	LIBIPW_DEBUG_INFO("Initializing...\n");
150
151	dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
152	if (!dev) {
153		LIBIPW_ERROR("Unable to allocate network device.\n");
154		goto failed;
155	}
156	ieee = netdev_priv(dev);
157
158	ieee->dev = dev;
159
160	err = libipw_networks_allocate(ieee);
161	if (err) {
162		LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
163		goto failed_free_netdev;
164	}
165	libipw_networks_initialize(ieee);
166
167	/* Default fragmentation threshold is maximum payload size */
168	ieee->fts = DEFAULT_FTS;
169	ieee->rts = DEFAULT_FTS;
170	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
171	ieee->open_wep = 1;
172
173	/* Default to enabling full open WEP with host based encrypt/decrypt */
174	ieee->host_encrypt = 1;
175	ieee->host_decrypt = 1;
176	ieee->host_mc_decrypt = 1;
177
178	/* Host fragementation in Open mode. Default is enabled.
179	 * Note: host fragmentation is always enabled if host encryption
180	 * is enabled. For cards can do hardware encryption, they must do
181	 * hardware fragmentation as well. So we don't need a variable
182	 * like host_enc_frag. */
183	ieee->host_open_frag = 1;
184	ieee->ieee802_1x = 1;	/* Default to supporting 802.1x */
185
186	spin_lock_init(&ieee->lock);
187
188	lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
189
190	ieee->wpa_enabled = 0;
191	ieee->drop_unencrypted = 0;
192	ieee->privacy_invoked = 0;
193
194	return dev;
195
196failed_free_netdev:
197	free_netdev(dev);
198failed:
199	return NULL;
200}
201
202void free_ieee80211(struct net_device *dev)
203{
204	struct libipw_device *ieee = netdev_priv(dev);
205
206	lib80211_crypt_info_free(&ieee->crypt_info);
207
208	libipw_networks_free(ieee);
209	free_netdev(dev);
210}
211
212#ifdef CONFIG_LIBIPW_DEBUG
213
214static int debug = 0;
215u32 libipw_debug_level = 0;
216EXPORT_SYMBOL_GPL(libipw_debug_level);
217static struct proc_dir_entry *libipw_proc = NULL;
218
219static int show_debug_level(char *page, char **start, off_t offset,
220			    int count, int *eof, void *data)
221{
222	return snprintf(page, count, "0x%08X\n", libipw_debug_level);
223}
224
225static int store_debug_level(struct file *file, const char __user * buffer,
226			     unsigned long count, void *data)
227{
228	char buf[] = "0x00000000\n";
229	unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
230	unsigned long val;
231
232	if (copy_from_user(buf, buffer, len))
233		return count;
234	buf[len] = 0;
235	if (sscanf(buf, "%li", &val) != 1)
236		printk(KERN_INFO DRV_NAME
237		       ": %s is not in hex or decimal form.\n", buf);
238	else
239		libipw_debug_level = val;
240
241	return strnlen(buf, len);
242}
243#endif				/* CONFIG_LIBIPW_DEBUG */
244
245static int __init libipw_init(void)
246{
247#ifdef CONFIG_LIBIPW_DEBUG
248	struct proc_dir_entry *e;
249
250	libipw_debug_level = debug;
251	libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
252	if (libipw_proc == NULL) {
253		LIBIPW_ERROR("Unable to create " DRV_NAME
254				" proc directory\n");
255		return -EIO;
256	}
257	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
258			      libipw_proc);
259	if (!e) {
260		remove_proc_entry(DRV_NAME, init_net.proc_net);
261		libipw_proc = NULL;
262		return -EIO;
263	}
264	e->read_proc = show_debug_level;
265	e->write_proc = store_debug_level;
266	e->data = NULL;
267#endif				/* CONFIG_LIBIPW_DEBUG */
268
269	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
270	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
271
272	return 0;
273}
274
275static void __exit libipw_exit(void)
276{
277#ifdef CONFIG_LIBIPW_DEBUG
278	if (libipw_proc) {
279		remove_proc_entry("debug_level", libipw_proc);
280		remove_proc_entry(DRV_NAME, init_net.proc_net);
281		libipw_proc = NULL;
282	}
283#endif				/* CONFIG_LIBIPW_DEBUG */
284}
285
286#ifdef CONFIG_LIBIPW_DEBUG
287#include <linux/moduleparam.h>
288module_param(debug, int, 0444);
289MODULE_PARM_DESC(debug, "debug output mask");
290#endif				/* CONFIG_LIBIPW_DEBUG */
291
292module_exit(libipw_exit);
293module_init(libipw_init);
294
295EXPORT_SYMBOL(alloc_ieee80211);
296EXPORT_SYMBOL(free_ieee80211);
297