]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/wireless/ipw2x00/libipw_module.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[net-next-2.6.git] / drivers / net / wireless / ipw2x00 / libipw_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
85d32e7b
JM
8 <j@w1.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
b453872c
JG
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:
c1eb2c82 28 Intel Linux Wireless <ilw@linux.intel.com>
b453872c
JG
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31*******************************************************************************/
32
33#include <linux/compiler.h>
b453872c
JG
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>
b453872c
JG
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>
b453872c
JG
47#include <linux/wireless.h>
48#include <linux/etherdevice.h>
49#include <asm/uaccess.h>
457c4cbc 50#include <net/net_namespace.h>
b453872c
JG
51#include <net/arp.h>
52
b0a4e7d8 53#include "libipw.h"
b453872c 54
31696160 55#define DRV_DESCRIPTION "802.11 data/management/control stack"
27ae60f8 56#define DRV_NAME "libipw"
b0a4e7d8 57#define DRV_VERSION LIBIPW_VERSION
31696160
JK
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);
b453872c
JG
63MODULE_LICENSE("GPL");
64
a3caa99e
JL
65struct cfg80211_ops libipw_config_ops = { };
66void *libipw_wiphy_privid = &libipw_wiphy_privid;
67
b0a4e7d8 68static int libipw_networks_allocate(struct libipw_device *ieee)
b453872c 69{
8e59340e
ZY
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 }
b453872c
JG
81 }
82
b453872c
JG
83 return 0;
84}
85
b0a4e7d8 86void libipw_network_reset(struct libipw_network *network)
15f38598
ZY
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
b0a4e7d8 97static inline void libipw_networks_free(struct libipw_device *ieee)
b453872c 98{
15f38598
ZY
99 int i;
100
8e59340e
ZY
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 }
b453872c
JG
106}
107
b0a4e7d8 108void libipw_networks_age(struct libipw_device *ieee,
c3d72b96
DW
109 unsigned long age_secs)
110{
b0a4e7d8 111 struct libipw_network *network = NULL;
c3d72b96
DW
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}
b0a4e7d8 121EXPORT_SYMBOL(libipw_networks_age);
c3d72b96 122
b0a4e7d8 123static void libipw_networks_initialize(struct libipw_device *ieee)
b453872c
JG
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++)
8e59340e 130 list_add_tail(&ieee->networks[i]->list,
0edd5b44 131 &ieee->network_free_list);
b453872c
JG
132}
133
b0a4e7d8 134int libipw_change_mtu(struct net_device *dev, int new_mtu)
42a4cf95 135{
b0a4e7d8 136 if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
42a4cf95
MC
137 return -EINVAL;
138 dev->mtu = new_mtu;
139 return 0;
140}
b0a4e7d8 141EXPORT_SYMBOL(libipw_change_mtu);
42a4cf95 142
27ae60f8 143struct net_device *alloc_libipw(int sizeof_priv, int monitor)
b453872c 144{
b0a4e7d8 145 struct libipw_device *ieee;
b453872c
JG
146 struct net_device *dev;
147 int err;
148
b0a4e7d8 149 LIBIPW_DEBUG_INFO("Initializing...\n");
b453872c 150
b0a4e7d8 151 dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
b453872c 152 if (!dev) {
b0a4e7d8 153 LIBIPW_ERROR("Unable to allocate network device.\n");
b453872c
JG
154 goto failed;
155 }
156 ieee = netdev_priv(dev);
b453872c
JG
157
158 ieee->dev = dev;
159
a3caa99e
JL
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
b0a4e7d8 181 err = libipw_networks_allocate(ieee);
b453872c 182 if (err) {
b0a4e7d8 183 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
a3caa99e 184 goto failed_free_wiphy;
b453872c 185 }
b0a4e7d8 186 libipw_networks_initialize(ieee);
b453872c
JG
187
188 /* Default fragmentation threshold is maximum payload size */
189 ieee->fts = DEFAULT_FTS;
3cdd00c5 190 ieee->rts = DEFAULT_FTS;
b453872c
JG
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;
ccd0fda3
JK
197 ieee->host_mc_decrypt = 1;
198
af901ca1 199 /* Host fragmentation in Open mode. Default is enabled.
1264fc04
JK
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;
0edd5b44 205 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
b453872c 206
b453872c
JG
207 spin_lock_init(&ieee->lock);
208
2ba4b32e 209 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
274bfb8d 210
0edd5b44 211 ieee->wpa_enabled = 0;
0edd5b44
JG
212 ieee->drop_unencrypted = 0;
213 ieee->privacy_invoked = 0;
b453872c
JG
214
215 return dev;
216
a3caa99e
JL
217failed_free_wiphy:
218 if (!monitor)
219 wiphy_free(ieee->wdev.wiphy);
d92a8e81
JL
220failed_free_netdev:
221 free_netdev(dev);
222failed:
b453872c
JG
223 return NULL;
224}
27ae60f8 225EXPORT_SYMBOL(alloc_libipw);
b453872c 226
27ae60f8 227void free_libipw(struct net_device *dev, int monitor)
b453872c 228{
b0a4e7d8 229 struct libipw_device *ieee = netdev_priv(dev);
b453872c 230
2ba4b32e 231 lib80211_crypt_info_free(&ieee->crypt_info);
b453872c 232
b0a4e7d8 233 libipw_networks_free(ieee);
a3caa99e
JL
234
235 /* free cfg80211 resources */
236 if (!monitor)
237 wiphy_free(ieee->wdev.wiphy);
238
b453872c
JG
239 free_netdev(dev);
240}
27ae60f8 241EXPORT_SYMBOL(free_libipw);
b453872c 242
3756162b 243#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
244
245static int debug = 0;
b0a4e7d8
JL
246u32 libipw_debug_level = 0;
247EXPORT_SYMBOL_GPL(libipw_debug_level);
248static struct proc_dir_entry *libipw_proc = NULL;
b453872c 249
b8d83392 250static int debug_level_proc_show(struct seq_file *m, void *v)
b453872c 251{
b8d83392
AD
252 seq_printf(m, "0x%08X\n", libipw_debug_level);
253 return 0;
b453872c
JG
254}
255
b8d83392
AD
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)
b453872c 263{
262d8e46 264 char buf[] = "0x00000000\n";
b8d83392 265 size_t len = min(sizeof(buf) - 1, count);
b453872c
JG
266 unsigned long val;
267
262d8e46 268 if (copy_from_user(buf, buffer, len))
b453872c 269 return count;
262d8e46
JK
270 buf[len] = 0;
271 if (sscanf(buf, "%li", &val) != 1)
b453872c
JG
272 printk(KERN_INFO DRV_NAME
273 ": %s is not in hex or decimal form.\n", buf);
274 else
b0a4e7d8 275 libipw_debug_level = val;
b453872c 276
262d8e46 277 return strnlen(buf, len);
b453872c 278}
b8d83392
AD
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};
3756162b 288#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 289
b0a4e7d8 290static int __init libipw_init(void)
b453872c 291{
3756162b 292#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
293 struct proc_dir_entry *e;
294
b0a4e7d8 295 libipw_debug_level = debug;
27ae60f8 296 libipw_proc = proc_mkdir("ieee80211", init_net.proc_net);
b0a4e7d8
JL
297 if (libipw_proc == NULL) {
298 LIBIPW_ERROR("Unable to create " DRV_NAME
b453872c
JG
299 " proc directory\n");
300 return -EIO;
301 }
b8d83392
AD
302 e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
303 &debug_level_proc_fops);
b453872c 304 if (!e) {
457c4cbc 305 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 306 libipw_proc = NULL;
b453872c
JG
307 return -EIO;
308 }
3756162b 309#endif /* CONFIG_LIBIPW_DEBUG */
31696160
JK
310
311 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
312 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
b453872c
JG
313
314 return 0;
315}
316
b0a4e7d8 317static void __exit libipw_exit(void)
b453872c 318{
3756162b 319#ifdef CONFIG_LIBIPW_DEBUG
b0a4e7d8
JL
320 if (libipw_proc) {
321 remove_proc_entry("debug_level", libipw_proc);
457c4cbc 322 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 323 libipw_proc = NULL;
b453872c 324 }
3756162b 325#endif /* CONFIG_LIBIPW_DEBUG */
b453872c
JG
326}
327
3756162b 328#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
329#include <linux/moduleparam.h>
330module_param(debug, int, 0444);
331MODULE_PARM_DESC(debug, "debug output mask");
3756162b 332#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 333
b0a4e7d8
JL
334module_exit(libipw_exit);
335module_init(libipw_init);