cfg80211: check lost scans later, fix bug
[GitHub/mt8127/android_kernel_alcatel_ttab.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:
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>
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
f3734ee6 53#include "ieee80211.h"
b453872c 54
31696160
JK
55#define DRV_DESCRIPTION "802.11 data/management/control stack"
56#define DRV_NAME "ieee80211"
57#define DRV_VERSION IEEE80211_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);
b453872c
JG
63MODULE_LICENSE("GPL");
64
858119e1 65static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
b453872c
JG
66{
67 if (ieee->networks)
68 return 0;
69
0edd5b44 70 ieee->networks =
571d6eee 71 kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
0edd5b44 72 GFP_KERNEL);
b453872c
JG
73 if (!ieee->networks) {
74 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
75 ieee->dev->name);
76 return -ENOMEM;
77 }
78
b453872c
JG
79 return 0;
80}
81
15f38598
ZY
82void ieee80211_network_reset(struct ieee80211_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
b453872c
JG
93static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
94{
15f38598
ZY
95 int i;
96
b453872c
JG
97 if (!ieee->networks)
98 return;
15f38598
ZY
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
b453872c
JG
104 kfree(ieee->networks);
105 ieee->networks = NULL;
106}
107
c3d72b96
DW
108void ieee80211_networks_age(struct ieee80211_device *ieee,
109 unsigned long age_secs)
110{
111 struct ieee80211_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(ieee80211_networks_age);
122
858119e1 123static void ieee80211_networks_initialize(struct ieee80211_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++)
0edd5b44
JG
130 list_add_tail(&ieee->networks[i].list,
131 &ieee->network_free_list);
b453872c
JG
132}
133
d5b3b9ae 134int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
42a4cf95
MC
135{
136 if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN))
137 return -EINVAL;
138 dev->mtu = new_mtu;
139 return 0;
140}
d5b3b9ae 141EXPORT_SYMBOL(ieee80211_change_mtu);
42a4cf95 142
b453872c
JG
143struct net_device *alloc_ieee80211(int sizeof_priv)
144{
145 struct ieee80211_device *ieee;
146 struct net_device *dev;
147 int err;
148
149 IEEE80211_DEBUG_INFO("Initializing...\n");
150
151 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
152 if (!dev) {
a76193df 153 IEEE80211_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
160 err = ieee80211_networks_allocate(ieee);
161 if (err) {
0edd5b44 162 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
d92a8e81 163 goto failed_free_netdev;
b453872c
JG
164 }
165 ieee80211_networks_initialize(ieee);
166
167 /* Default fragmentation threshold is maximum payload size */
168 ieee->fts = DEFAULT_FTS;
3cdd00c5 169 ieee->rts = DEFAULT_FTS;
b453872c
JG
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;
ccd0fda3
JK
176 ieee->host_mc_decrypt = 1;
177
1264fc04
JK
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;
0edd5b44 184 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
b453872c 185
b453872c
JG
186 spin_lock_init(&ieee->lock);
187
2ba4b32e 188 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
274bfb8d 189
0edd5b44 190 ieee->wpa_enabled = 0;
0edd5b44
JG
191 ieee->drop_unencrypted = 0;
192 ieee->privacy_invoked = 0;
b453872c
JG
193
194 return dev;
195
d92a8e81
JL
196failed_free_netdev:
197 free_netdev(dev);
198failed:
b453872c
JG
199 return NULL;
200}
201
b453872c
JG
202void free_ieee80211(struct net_device *dev)
203{
204 struct ieee80211_device *ieee = netdev_priv(dev);
205
2ba4b32e 206 lib80211_crypt_info_free(&ieee->crypt_info);
b453872c
JG
207
208 ieee80211_networks_free(ieee);
209 free_netdev(dev);
210}
211
3756162b 212#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
213
214static int debug = 0;
215u32 ieee80211_debug_level = 0;
2933d42c 216EXPORT_SYMBOL_GPL(ieee80211_debug_level);
b7cffb02 217static struct proc_dir_entry *ieee80211_proc = NULL;
b453872c
JG
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", ieee80211_debug_level);
223}
224
0edd5b44 225static int store_debug_level(struct file *file, const char __user * buffer,
b453872c
JG
226 unsigned long count, void *data)
227{
262d8e46
JK
228 char buf[] = "0x00000000\n";
229 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
b453872c
JG
230 unsigned long val;
231
262d8e46 232 if (copy_from_user(buf, buffer, len))
b453872c 233 return count;
262d8e46
JK
234 buf[len] = 0;
235 if (sscanf(buf, "%li", &val) != 1)
b453872c
JG
236 printk(KERN_INFO DRV_NAME
237 ": %s is not in hex or decimal form.\n", buf);
238 else
239 ieee80211_debug_level = val;
240
262d8e46 241 return strnlen(buf, len);
b453872c 242}
3756162b 243#endif /* CONFIG_LIBIPW_DEBUG */
b453872c
JG
244
245static int __init ieee80211_init(void)
246{
3756162b 247#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
248 struct proc_dir_entry *e;
249
250 ieee80211_debug_level = debug;
457c4cbc 251 ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
b453872c
JG
252 if (ieee80211_proc == NULL) {
253 IEEE80211_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 ieee80211_proc);
259 if (!e) {
457c4cbc 260 remove_proc_entry(DRV_NAME, init_net.proc_net);
b453872c
JG
261 ieee80211_proc = NULL;
262 return -EIO;
263 }
264 e->read_proc = show_debug_level;
265 e->write_proc = store_debug_level;
266 e->data = NULL;
3756162b 267#endif /* CONFIG_LIBIPW_DEBUG */
31696160
JK
268
269 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
270 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
b453872c
JG
271
272 return 0;
273}
274
275static void __exit ieee80211_exit(void)
276{
3756162b 277#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
278 if (ieee80211_proc) {
279 remove_proc_entry("debug_level", ieee80211_proc);
457c4cbc 280 remove_proc_entry(DRV_NAME, init_net.proc_net);
b453872c
JG
281 ieee80211_proc = NULL;
282 }
3756162b 283#endif /* CONFIG_LIBIPW_DEBUG */
b453872c
JG
284}
285
3756162b 286#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
287#include <linux/moduleparam.h>
288module_param(debug, int, 0444);
289MODULE_PARM_DESC(debug, "debug output mask");
3756162b 290#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 291
b453872c
JG
292module_exit(ieee80211_exit);
293module_init(ieee80211_init);
b453872c
JG
294
295EXPORT_SYMBOL(alloc_ieee80211);
296EXPORT_SYMBOL(free_ieee80211);