1 /*******************************************************************************
3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
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
9 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
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.
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
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.
24 The full GNU General Public License is included in this distribution in the
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
31 *******************************************************************************/
33 #include <linux/compiler.h>
34 #include <linux/errno.h>
35 #include <linux/if_arp.h>
36 #include <linux/in6.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>
53 #include "ieee80211.h"
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>"
60 MODULE_VERSION(DRV_VERSION);
61 MODULE_DESCRIPTION(DRV_DESCRIPTION);
62 MODULE_AUTHOR(DRV_COPYRIGHT);
63 MODULE_LICENSE("GPL");
65 static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
71 kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
73 if (!ieee->networks) {
74 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
82 void ieee80211_network_reset(struct ieee80211_network *network)
87 if (network->ibss_dfs) {
88 kfree(network->ibss_dfs);
89 network->ibss_dfs = NULL;
93 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
100 for (i = 0; i < MAX_NETWORK_COUNT; i++)
101 if (ieee->networks[i].ibss_dfs)
102 kfree(ieee->networks[i].ibss_dfs);
104 kfree(ieee->networks);
105 ieee->networks = NULL;
108 void ieee80211_networks_age(struct ieee80211_device *ieee,
109 unsigned long age_secs)
111 struct ieee80211_network *network = NULL;
113 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
115 spin_lock_irqsave(&ieee->lock, flags);
116 list_for_each_entry(network, &ieee->network_list, list) {
117 network->last_scanned -= age_jiffies;
119 spin_unlock_irqrestore(&ieee->lock, flags);
121 EXPORT_SYMBOL(ieee80211_networks_age);
123 static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
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);
134 static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
136 if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN))
142 static struct net_device_stats *ieee80211_generic_get_stats(
143 struct net_device *dev)
145 struct ieee80211_device *ieee = netdev_priv(dev);
149 struct net_device *alloc_ieee80211(int sizeof_priv)
151 struct ieee80211_device *ieee;
152 struct net_device *dev;
155 IEEE80211_DEBUG_INFO("Initializing...\n");
157 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
159 IEEE80211_ERROR("Unable to allocate network device.\n");
162 ieee = netdev_priv(dev);
163 dev->hard_start_xmit = ieee80211_xmit;
164 dev->change_mtu = ieee80211_change_mtu;
166 /* Drivers are free to override this if the generic implementation
167 * does not meet their needs. */
168 dev->get_stats = ieee80211_generic_get_stats;
172 err = ieee80211_networks_allocate(ieee);
174 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
175 goto failed_free_netdev;
177 ieee80211_networks_initialize(ieee);
179 /* Default fragmentation threshold is maximum payload size */
180 ieee->fts = DEFAULT_FTS;
181 ieee->rts = DEFAULT_FTS;
182 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
185 /* Default to enabling full open WEP with host based encrypt/decrypt */
186 ieee->host_encrypt = 1;
187 ieee->host_decrypt = 1;
188 ieee->host_mc_decrypt = 1;
190 /* Host fragementation in Open mode. Default is enabled.
191 * Note: host fragmentation is always enabled if host encryption
192 * is enabled. For cards can do hardware encryption, they must do
193 * hardware fragmentation as well. So we don't need a variable
194 * like host_enc_frag. */
195 ieee->host_open_frag = 1;
196 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
198 spin_lock_init(&ieee->lock);
200 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
202 ieee->wpa_enabled = 0;
203 ieee->drop_unencrypted = 0;
204 ieee->privacy_invoked = 0;
214 void free_ieee80211(struct net_device *dev)
216 struct ieee80211_device *ieee = netdev_priv(dev);
218 lib80211_crypt_info_free(&ieee->crypt_info);
220 ieee80211_networks_free(ieee);
224 #ifdef CONFIG_IEEE80211_DEBUG
226 static int debug = 0;
227 u32 ieee80211_debug_level = 0;
228 EXPORT_SYMBOL_GPL(ieee80211_debug_level);
229 static struct proc_dir_entry *ieee80211_proc = NULL;
231 static int show_debug_level(char *page, char **start, off_t offset,
232 int count, int *eof, void *data)
234 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
237 static int store_debug_level(struct file *file, const char __user * buffer,
238 unsigned long count, void *data)
240 char buf[] = "0x00000000\n";
241 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
244 if (copy_from_user(buf, buffer, len))
247 if (sscanf(buf, "%li", &val) != 1)
248 printk(KERN_INFO DRV_NAME
249 ": %s is not in hex or decimal form.\n", buf);
251 ieee80211_debug_level = val;
253 return strnlen(buf, len);
255 #endif /* CONFIG_IEEE80211_DEBUG */
257 static int __init ieee80211_init(void)
259 #ifdef CONFIG_IEEE80211_DEBUG
260 struct proc_dir_entry *e;
262 ieee80211_debug_level = debug;
263 ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
264 if (ieee80211_proc == NULL) {
265 IEEE80211_ERROR("Unable to create " DRV_NAME
266 " proc directory\n");
269 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
272 remove_proc_entry(DRV_NAME, init_net.proc_net);
273 ieee80211_proc = NULL;
276 e->read_proc = show_debug_level;
277 e->write_proc = store_debug_level;
279 #endif /* CONFIG_IEEE80211_DEBUG */
281 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
282 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
287 static void __exit ieee80211_exit(void)
289 #ifdef CONFIG_IEEE80211_DEBUG
290 if (ieee80211_proc) {
291 remove_proc_entry("debug_level", ieee80211_proc);
292 remove_proc_entry(DRV_NAME, init_net.proc_net);
293 ieee80211_proc = NULL;
295 #endif /* CONFIG_IEEE80211_DEBUG */
298 #ifdef CONFIG_IEEE80211_DEBUG
299 #include <linux/moduleparam.h>
300 module_param(debug, int, 0444);
301 MODULE_PARM_DESC(debug, "debug output mask");
302 #endif /* CONFIG_IEEE80211_DEBUG */
304 module_exit(ieee80211_exit);
305 module_init(ieee80211_init);
307 EXPORT_SYMBOL(alloc_ieee80211);
308 EXPORT_SYMBOL(free_ieee80211);