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 <jkmaline@cc.hut.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/config.h>
35 #include <linux/errno.h>
36 #include <linux/if_arp.h>
37 #include <linux/in6.h>
40 #include <linux/kernel.h>
41 #include <linux/module.h>
42 #include <linux/netdevice.h>
43 #include <linux/proc_fs.h>
44 #include <linux/skbuff.h>
45 #include <linux/slab.h>
46 #include <linux/tcp.h>
47 #include <linux/types.h>
48 #include <linux/wireless.h>
49 #include <linux/etherdevice.h>
50 #include <asm/uaccess.h>
53 #include <net/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 inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
71 kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
73 if (!ieee->networks) {
74 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
79 memset(ieee->networks, 0,
80 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
85 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
89 kfree(ieee->networks);
90 ieee->networks = NULL;
93 static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
97 INIT_LIST_HEAD(&ieee->network_free_list);
98 INIT_LIST_HEAD(&ieee->network_list);
99 for (i = 0; i < MAX_NETWORK_COUNT; i++)
100 list_add_tail(&ieee->networks[i].list,
101 &ieee->network_free_list);
104 struct net_device *alloc_ieee80211(int sizeof_priv)
106 struct ieee80211_device *ieee;
107 struct net_device *dev;
110 IEEE80211_DEBUG_INFO("Initializing...\n");
112 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
114 IEEE80211_ERROR("Unable to network device.\n");
117 ieee = netdev_priv(dev);
118 dev->hard_start_xmit = ieee80211_xmit;
122 err = ieee80211_networks_allocate(ieee);
124 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
127 ieee80211_networks_initialize(ieee);
129 /* Default fragmentation threshold is maximum payload size */
130 ieee->fts = DEFAULT_FTS;
131 ieee->rts = DEFAULT_FTS;
132 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
135 /* Default to enabling full open WEP with host based encrypt/decrypt */
136 ieee->host_encrypt = 1;
137 ieee->host_decrypt = 1;
138 ieee->host_mc_decrypt = 1;
140 /* Host fragementation in Open mode. Default is enabled.
141 * Note: host fragmentation is always enabled if host encryption
142 * is enabled. For cards can do hardware encryption, they must do
143 * hardware fragmentation as well. So we don't need a variable
144 * like host_enc_frag. */
145 ieee->host_open_frag = 1;
146 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
148 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
149 init_timer(&ieee->crypt_deinit_timer);
150 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
151 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
152 ieee->crypt_quiesced = 0;
154 spin_lock_init(&ieee->lock);
156 ieee->wpa_enabled = 0;
157 ieee->drop_unencrypted = 0;
158 ieee->privacy_invoked = 0;
168 void free_ieee80211(struct net_device *dev)
170 struct ieee80211_device *ieee = netdev_priv(dev);
174 ieee80211_crypt_quiescing(ieee);
175 del_timer_sync(&ieee->crypt_deinit_timer);
176 ieee80211_crypt_deinit_entries(ieee, 1);
178 for (i = 0; i < WEP_KEYS; i++) {
179 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
182 crypt->ops->deinit(crypt->priv);
183 module_put(crypt->ops->owner);
186 ieee->crypt[i] = NULL;
190 ieee80211_networks_free(ieee);
194 #ifdef CONFIG_IEEE80211_DEBUG
196 static int debug = 0;
197 u32 ieee80211_debug_level = 0;
198 struct proc_dir_entry *ieee80211_proc = NULL;
200 static int show_debug_level(char *page, char **start, off_t offset,
201 int count, int *eof, void *data)
203 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
206 static int store_debug_level(struct file *file, const char __user * buffer,
207 unsigned long count, void *data)
209 char buf[] = "0x00000000\n";
210 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
213 if (copy_from_user(buf, buffer, len))
216 if (sscanf(buf, "%li", &val) != 1)
217 printk(KERN_INFO DRV_NAME
218 ": %s is not in hex or decimal form.\n", buf);
220 ieee80211_debug_level = val;
222 return strnlen(buf, len);
224 #endif /* CONFIG_IEEE80211_DEBUG */
226 static int __init ieee80211_init(void)
228 #ifdef CONFIG_IEEE80211_DEBUG
229 struct proc_dir_entry *e;
231 ieee80211_debug_level = debug;
232 ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
233 if (ieee80211_proc == NULL) {
234 IEEE80211_ERROR("Unable to create " DRV_NAME
235 " proc directory\n");
238 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
241 remove_proc_entry(DRV_NAME, proc_net);
242 ieee80211_proc = NULL;
245 e->read_proc = show_debug_level;
246 e->write_proc = store_debug_level;
248 #endif /* CONFIG_IEEE80211_DEBUG */
250 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
251 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
256 static void __exit ieee80211_exit(void)
258 #ifdef CONFIG_IEEE80211_DEBUG
259 if (ieee80211_proc) {
260 remove_proc_entry("debug_level", ieee80211_proc);
261 remove_proc_entry(DRV_NAME, proc_net);
262 ieee80211_proc = NULL;
264 #endif /* CONFIG_IEEE80211_DEBUG */
267 #ifdef CONFIG_IEEE80211_DEBUG
268 #include <linux/moduleparam.h>
269 module_param(debug, int, 0444);
270 MODULE_PARM_DESC(debug, "debug output mask");
271 #endif /* CONFIG_IEEE80211_DEBUG */
273 module_exit(ieee80211_exit);
274 module_init(ieee80211_init);
276 const char *escape_essid(const char *essid, u8 essid_len)
278 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
279 const char *s = essid;
282 if (ieee80211_is_empty_essid(essid, essid_len)) {
283 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
287 essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
288 while (essid_len--) {
301 EXPORT_SYMBOL(alloc_ieee80211);
302 EXPORT_SYMBOL(free_ieee80211);
303 EXPORT_SYMBOL(escape_essid);