]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/wireless/ipw2x00/libipw_module.c
ipw2x00: replace "ieee80211" with "libipw" where appropriate
[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
JG
69{
70 if (ieee->networks)
71 return 0;
72
0edd5b44 73 ieee->networks =
b0a4e7d8 74 kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network),
0edd5b44 75 GFP_KERNEL);
b453872c
JG
76 if (!ieee->networks) {
77 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
78 ieee->dev->name);
79 return -ENOMEM;
80 }
81
b453872c
JG
82 return 0;
83}
84
b0a4e7d8 85void libipw_network_reset(struct libipw_network *network)
15f38598
ZY
86{
87 if (!network)
88 return;
89
90 if (network->ibss_dfs) {
91 kfree(network->ibss_dfs);
92 network->ibss_dfs = NULL;
93 }
94}
95
b0a4e7d8 96static inline void libipw_networks_free(struct libipw_device *ieee)
b453872c 97{
15f38598
ZY
98 int i;
99
b453872c
JG
100 if (!ieee->networks)
101 return;
15f38598
ZY
102
103 for (i = 0; i < MAX_NETWORK_COUNT; i++)
104 if (ieee->networks[i].ibss_dfs)
105 kfree(ieee->networks[i].ibss_dfs);
106
b453872c
JG
107 kfree(ieee->networks);
108 ieee->networks = NULL;
109}
110
b0a4e7d8 111void libipw_networks_age(struct libipw_device *ieee,
c3d72b96
DW
112 unsigned long age_secs)
113{
b0a4e7d8 114 struct libipw_network *network = NULL;
c3d72b96
DW
115 unsigned long flags;
116 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
117
118 spin_lock_irqsave(&ieee->lock, flags);
119 list_for_each_entry(network, &ieee->network_list, list) {
120 network->last_scanned -= age_jiffies;
121 }
122 spin_unlock_irqrestore(&ieee->lock, flags);
123}
b0a4e7d8 124EXPORT_SYMBOL(libipw_networks_age);
c3d72b96 125
b0a4e7d8 126static void libipw_networks_initialize(struct libipw_device *ieee)
b453872c
JG
127{
128 int i;
129
130 INIT_LIST_HEAD(&ieee->network_free_list);
131 INIT_LIST_HEAD(&ieee->network_list);
132 for (i = 0; i < MAX_NETWORK_COUNT; i++)
0edd5b44
JG
133 list_add_tail(&ieee->networks[i].list,
134 &ieee->network_free_list);
b453872c
JG
135}
136
b0a4e7d8 137int libipw_change_mtu(struct net_device *dev, int new_mtu)
42a4cf95 138{
b0a4e7d8 139 if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
42a4cf95
MC
140 return -EINVAL;
141 dev->mtu = new_mtu;
142 return 0;
143}
b0a4e7d8 144EXPORT_SYMBOL(libipw_change_mtu);
42a4cf95 145
27ae60f8 146struct net_device *alloc_libipw(int sizeof_priv, int monitor)
b453872c 147{
b0a4e7d8 148 struct libipw_device *ieee;
b453872c
JG
149 struct net_device *dev;
150 int err;
151
b0a4e7d8 152 LIBIPW_DEBUG_INFO("Initializing...\n");
b453872c 153
b0a4e7d8 154 dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
b453872c 155 if (!dev) {
b0a4e7d8 156 LIBIPW_ERROR("Unable to allocate network device.\n");
b453872c
JG
157 goto failed;
158 }
159 ieee = netdev_priv(dev);
b453872c
JG
160
161 ieee->dev = dev;
162
a3caa99e
JL
163 if (!monitor) {
164 ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
165 if (!ieee->wdev.wiphy) {
166 LIBIPW_ERROR("Unable to allocate wiphy.\n");
167 goto failed_free_netdev;
168 }
169
170 ieee->dev->ieee80211_ptr = &ieee->wdev;
171 ieee->wdev.iftype = NL80211_IFTYPE_STATION;
172
173 /* Fill-out wiphy structure bits we know... Not enough info
174 here to call set_wiphy_dev or set MAC address or channel info
175 -- have to do that in ->ndo_init... */
176 ieee->wdev.wiphy->privid = libipw_wiphy_privid;
177
178 ieee->wdev.wiphy->max_scan_ssids = 1;
179 ieee->wdev.wiphy->max_scan_ie_len = 0;
180 ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
181 | BIT(NL80211_IFTYPE_ADHOC);
182 }
183
b0a4e7d8 184 err = libipw_networks_allocate(ieee);
b453872c 185 if (err) {
b0a4e7d8 186 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
a3caa99e 187 goto failed_free_wiphy;
b453872c 188 }
b0a4e7d8 189 libipw_networks_initialize(ieee);
b453872c
JG
190
191 /* Default fragmentation threshold is maximum payload size */
192 ieee->fts = DEFAULT_FTS;
3cdd00c5 193 ieee->rts = DEFAULT_FTS;
b453872c
JG
194 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
195 ieee->open_wep = 1;
196
197 /* Default to enabling full open WEP with host based encrypt/decrypt */
198 ieee->host_encrypt = 1;
199 ieee->host_decrypt = 1;
ccd0fda3
JK
200 ieee->host_mc_decrypt = 1;
201
af901ca1 202 /* Host fragmentation in Open mode. Default is enabled.
1264fc04
JK
203 * Note: host fragmentation is always enabled if host encryption
204 * is enabled. For cards can do hardware encryption, they must do
205 * hardware fragmentation as well. So we don't need a variable
206 * like host_enc_frag. */
207 ieee->host_open_frag = 1;
0edd5b44 208 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
b453872c 209
b453872c
JG
210 spin_lock_init(&ieee->lock);
211
2ba4b32e 212 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
274bfb8d 213
0edd5b44 214 ieee->wpa_enabled = 0;
0edd5b44
JG
215 ieee->drop_unencrypted = 0;
216 ieee->privacy_invoked = 0;
b453872c
JG
217
218 return dev;
219
a3caa99e
JL
220failed_free_wiphy:
221 if (!monitor)
222 wiphy_free(ieee->wdev.wiphy);
d92a8e81
JL
223failed_free_netdev:
224 free_netdev(dev);
225failed:
b453872c
JG
226 return NULL;
227}
27ae60f8 228EXPORT_SYMBOL(alloc_libipw);
b453872c 229
27ae60f8 230void free_libipw(struct net_device *dev, int monitor)
b453872c 231{
b0a4e7d8 232 struct libipw_device *ieee = netdev_priv(dev);
b453872c 233
2ba4b32e 234 lib80211_crypt_info_free(&ieee->crypt_info);
b453872c 235
b0a4e7d8 236 libipw_networks_free(ieee);
a3caa99e
JL
237
238 /* free cfg80211 resources */
239 if (!monitor)
240 wiphy_free(ieee->wdev.wiphy);
241
b453872c
JG
242 free_netdev(dev);
243}
27ae60f8 244EXPORT_SYMBOL(free_libipw);
b453872c 245
3756162b 246#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
247
248static int debug = 0;
b0a4e7d8
JL
249u32 libipw_debug_level = 0;
250EXPORT_SYMBOL_GPL(libipw_debug_level);
251static struct proc_dir_entry *libipw_proc = NULL;
b453872c 252
b8d83392 253static int debug_level_proc_show(struct seq_file *m, void *v)
b453872c 254{
b8d83392
AD
255 seq_printf(m, "0x%08X\n", libipw_debug_level);
256 return 0;
b453872c
JG
257}
258
b8d83392
AD
259static int debug_level_proc_open(struct inode *inode, struct file *file)
260{
261 return single_open(file, debug_level_proc_show, NULL);
262}
263
264static ssize_t debug_level_proc_write(struct file *file,
265 const char __user *buffer, size_t count, loff_t *pos)
b453872c 266{
262d8e46 267 char buf[] = "0x00000000\n";
b8d83392 268 size_t len = min(sizeof(buf) - 1, count);
b453872c
JG
269 unsigned long val;
270
262d8e46 271 if (copy_from_user(buf, buffer, len))
b453872c 272 return count;
262d8e46
JK
273 buf[len] = 0;
274 if (sscanf(buf, "%li", &val) != 1)
b453872c
JG
275 printk(KERN_INFO DRV_NAME
276 ": %s is not in hex or decimal form.\n", buf);
277 else
b0a4e7d8 278 libipw_debug_level = val;
b453872c 279
262d8e46 280 return strnlen(buf, len);
b453872c 281}
b8d83392
AD
282
283static const struct file_operations debug_level_proc_fops = {
284 .owner = THIS_MODULE,
285 .open = debug_level_proc_open,
286 .read = seq_read,
287 .llseek = seq_lseek,
288 .release = single_release,
289 .write = debug_level_proc_write,
290};
3756162b 291#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 292
b0a4e7d8 293static int __init libipw_init(void)
b453872c 294{
3756162b 295#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
296 struct proc_dir_entry *e;
297
b0a4e7d8 298 libipw_debug_level = debug;
27ae60f8 299 libipw_proc = proc_mkdir("ieee80211", init_net.proc_net);
b0a4e7d8
JL
300 if (libipw_proc == NULL) {
301 LIBIPW_ERROR("Unable to create " DRV_NAME
b453872c
JG
302 " proc directory\n");
303 return -EIO;
304 }
b8d83392
AD
305 e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
306 &debug_level_proc_fops);
b453872c 307 if (!e) {
457c4cbc 308 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 309 libipw_proc = NULL;
b453872c
JG
310 return -EIO;
311 }
3756162b 312#endif /* CONFIG_LIBIPW_DEBUG */
31696160
JK
313
314 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
315 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
b453872c
JG
316
317 return 0;
318}
319
b0a4e7d8 320static void __exit libipw_exit(void)
b453872c 321{
3756162b 322#ifdef CONFIG_LIBIPW_DEBUG
b0a4e7d8
JL
323 if (libipw_proc) {
324 remove_proc_entry("debug_level", libipw_proc);
457c4cbc 325 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 326 libipw_proc = NULL;
b453872c 327 }
3756162b 328#endif /* CONFIG_LIBIPW_DEBUG */
b453872c
JG
329}
330
3756162b 331#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
332#include <linux/moduleparam.h>
333module_param(debug, int, 0444);
334MODULE_PARM_DESC(debug, "debug output mask");
3756162b 335#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 336
b0a4e7d8
JL
337module_exit(libipw_exit);
338module_init(libipw_init);