• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/net/wireless/ipw2x00/
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  Intel Linux Wireless <ilw@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        "libipw"
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 struct cfg80211_ops libipw_config_ops = { };
66static void *libipw_wiphy_privid = &libipw_wiphy_privid;
67
68static int libipw_networks_allocate(struct libipw_device *ieee)
69{
70	int i, j;
71
72	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
73		ieee->networks[i] = kzalloc(sizeof(struct libipw_network),
74					    GFP_KERNEL);
75		if (!ieee->networks[i]) {
76			LIBIPW_ERROR("Out of memory allocating beacons\n");
77			for (j = 0; j < i; j++)
78				kfree(ieee->networks[j]);
79			return -ENOMEM;
80		}
81	}
82
83	return 0;
84}
85
86void libipw_network_reset(struct libipw_network *network)
87{
88	if (!network)
89		return;
90
91	if (network->ibss_dfs) {
92		kfree(network->ibss_dfs);
93		network->ibss_dfs = NULL;
94	}
95}
96
97static inline void libipw_networks_free(struct libipw_device *ieee)
98{
99	int i;
100
101	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
102		if (ieee->networks[i]->ibss_dfs)
103			kfree(ieee->networks[i]->ibss_dfs);
104		kfree(ieee->networks[i]);
105	}
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_libipw(int sizeof_priv, int monitor)
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	if (!monitor) {
161		ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
162		if (!ieee->wdev.wiphy) {
163			LIBIPW_ERROR("Unable to allocate wiphy.\n");
164			goto failed_free_netdev;
165		}
166
167		ieee->dev->ieee80211_ptr = &ieee->wdev;
168		ieee->wdev.iftype = NL80211_IFTYPE_STATION;
169
170		/* Fill-out wiphy structure bits we know...  Not enough info
171		   here to call set_wiphy_dev or set MAC address or channel info
172		   -- have to do that in ->ndo_init... */
173		ieee->wdev.wiphy->privid = libipw_wiphy_privid;
174
175		ieee->wdev.wiphy->max_scan_ssids = 1;
176		ieee->wdev.wiphy->max_scan_ie_len = 0;
177		ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
178						| BIT(NL80211_IFTYPE_ADHOC);
179	}
180
181	err = libipw_networks_allocate(ieee);
182	if (err) {
183		LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
184		goto failed_free_wiphy;
185	}
186	libipw_networks_initialize(ieee);
187
188	/* Default fragmentation threshold is maximum payload size */
189	ieee->fts = DEFAULT_FTS;
190	ieee->rts = DEFAULT_FTS;
191	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
192	ieee->open_wep = 1;
193
194	/* Default to enabling full open WEP with host based encrypt/decrypt */
195	ieee->host_encrypt = 1;
196	ieee->host_decrypt = 1;
197	ieee->host_mc_decrypt = 1;
198
199	/* Host fragmentation in Open mode. Default is enabled.
200	 * Note: host fragmentation is always enabled if host encryption
201	 * is enabled. For cards can do hardware encryption, they must do
202	 * hardware fragmentation as well. So we don't need a variable
203	 * like host_enc_frag. */
204	ieee->host_open_frag = 1;
205	ieee->ieee802_1x = 1;	/* Default to supporting 802.1x */
206
207	spin_lock_init(&ieee->lock);
208
209	lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
210
211	ieee->wpa_enabled = 0;
212	ieee->drop_unencrypted = 0;
213	ieee->privacy_invoked = 0;
214
215	return dev;
216
217failed_free_wiphy:
218	if (!monitor)
219		wiphy_free(ieee->wdev.wiphy);
220failed_free_netdev:
221	free_netdev(dev);
222failed:
223	return NULL;
224}
225EXPORT_SYMBOL(alloc_libipw);
226
227void free_libipw(struct net_device *dev, int monitor)
228{
229	struct libipw_device *ieee = netdev_priv(dev);
230
231	lib80211_crypt_info_free(&ieee->crypt_info);
232
233	libipw_networks_free(ieee);
234
235	/* free cfg80211 resources */
236	if (!monitor)
237		wiphy_free(ieee->wdev.wiphy);
238
239	free_netdev(dev);
240}
241EXPORT_SYMBOL(free_libipw);
242
243#ifdef CONFIG_LIBIPW_DEBUG
244
245static int debug = 0;
246u32 libipw_debug_level = 0;
247EXPORT_SYMBOL_GPL(libipw_debug_level);
248static struct proc_dir_entry *libipw_proc = NULL;
249
250static int debug_level_proc_show(struct seq_file *m, void *v)
251{
252	seq_printf(m, "0x%08X\n", libipw_debug_level);
253	return 0;
254}
255
256static int debug_level_proc_open(struct inode *inode, struct file *file)
257{
258	return single_open(file, debug_level_proc_show, NULL);
259}
260
261static ssize_t debug_level_proc_write(struct file *file,
262		const char __user *buffer, size_t count, loff_t *pos)
263{
264	char buf[] = "0x00000000\n";
265	size_t len = min(sizeof(buf) - 1, count);
266	unsigned long val;
267
268	if (copy_from_user(buf, buffer, len))
269		return count;
270	buf[len] = 0;
271	if (sscanf(buf, "%li", &val) != 1)
272		printk(KERN_INFO DRV_NAME
273		       ": %s is not in hex or decimal form.\n", buf);
274	else
275		libipw_debug_level = val;
276
277	return strnlen(buf, len);
278}
279
280static const struct file_operations debug_level_proc_fops = {
281	.owner		= THIS_MODULE,
282	.open		= debug_level_proc_open,
283	.read		= seq_read,
284	.llseek		= seq_lseek,
285	.release	= single_release,
286	.write		= debug_level_proc_write,
287};
288#endif				/* CONFIG_LIBIPW_DEBUG */
289
290static int __init libipw_init(void)
291{
292#ifdef CONFIG_LIBIPW_DEBUG
293	struct proc_dir_entry *e;
294
295	libipw_debug_level = debug;
296	libipw_proc = proc_mkdir("ieee80211", init_net.proc_net);
297	if (libipw_proc == NULL) {
298		LIBIPW_ERROR("Unable to create " DRV_NAME
299				" proc directory\n");
300		return -EIO;
301	}
302	e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
303			&debug_level_proc_fops);
304	if (!e) {
305		remove_proc_entry(DRV_NAME, init_net.proc_net);
306		libipw_proc = NULL;
307		return -EIO;
308	}
309#endif				/* CONFIG_LIBIPW_DEBUG */
310
311	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
312	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
313
314	return 0;
315}
316
317static void __exit libipw_exit(void)
318{
319#ifdef CONFIG_LIBIPW_DEBUG
320	if (libipw_proc) {
321		remove_proc_entry("debug_level", libipw_proc);
322		remove_proc_entry(DRV_NAME, init_net.proc_net);
323		libipw_proc = NULL;
324	}
325#endif				/* CONFIG_LIBIPW_DEBUG */
326}
327
328#ifdef CONFIG_LIBIPW_DEBUG
329#include <linux/moduleparam.h>
330module_param(debug, int, 0444);
331MODULE_PARM_DESC(debug, "debug output mask");
332#endif				/* CONFIG_LIBIPW_DEBUG */
333
334module_exit(libipw_exit);
335module_init(libipw_init);
336