[PATCH] ieee80211: Type-o, capbility definition for QoS, and ERP parsing
[linux-2.6-block.git] / net / ieee80211 / ieee80211_module.c
1 /*******************************************************************************
2
3   Copyright(c) 2004 Intel Corporation. All rights reserved.
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
8   <jkmaline@cc.hut.fi>
9   Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
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>
34 #include <linux/config.h>
35 #include <linux/errno.h>
36 #include <linux/if_arp.h>
37 #include <linux/in6.h>
38 #include <linux/in.h>
39 #include <linux/ip.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/version.h>
49 #include <linux/wireless.h>
50 #include <linux/etherdevice.h>
51 #include <asm/uaccess.h>
52 #include <net/arp.h>
53
54 #include <net/ieee80211.h>
55
56 MODULE_DESCRIPTION("802.11 data/management/control stack");
57 MODULE_AUTHOR
58     ("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
59 MODULE_LICENSE("GPL");
60
61 #define DRV_NAME "ieee80211"
62
63 static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
64 {
65         if (ieee->networks)
66                 return 0;
67
68         ieee->networks =
69             kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
70                     GFP_KERNEL);
71         if (!ieee->networks) {
72                 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
73                        ieee->dev->name);
74                 return -ENOMEM;
75         }
76
77         memset(ieee->networks, 0,
78                MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
79
80         return 0;
81 }
82
83 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
84 {
85         if (!ieee->networks)
86                 return;
87         kfree(ieee->networks);
88         ieee->networks = NULL;
89 }
90
91 static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
92 {
93         int i;
94
95         INIT_LIST_HEAD(&ieee->network_free_list);
96         INIT_LIST_HEAD(&ieee->network_list);
97         for (i = 0; i < MAX_NETWORK_COUNT; i++)
98                 list_add_tail(&ieee->networks[i].list,
99                               &ieee->network_free_list);
100 }
101
102 struct net_device *alloc_ieee80211(int sizeof_priv)
103 {
104         struct ieee80211_device *ieee;
105         struct net_device *dev;
106         int err;
107
108         IEEE80211_DEBUG_INFO("Initializing...\n");
109
110         dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
111         if (!dev) {
112                 IEEE80211_ERROR("Unable to network device.\n");
113                 goto failed;
114         }
115         ieee = netdev_priv(dev);
116         dev->hard_start_xmit = ieee80211_xmit;
117
118         ieee->dev = dev;
119
120         err = ieee80211_networks_allocate(ieee);
121         if (err) {
122                 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
123                 goto failed;
124         }
125         ieee80211_networks_initialize(ieee);
126
127         /* Default fragmentation threshold is maximum payload size */
128         ieee->fts = DEFAULT_FTS;
129         ieee->rts = DEFAULT_FTS;
130         ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
131         ieee->open_wep = 1;
132
133         /* Default to enabling full open WEP with host based encrypt/decrypt */
134         ieee->host_encrypt = 1;
135         ieee->host_decrypt = 1;
136         /* Host fragementation in Open mode. Default is enabled.
137          * Note: host fragmentation is always enabled if host encryption
138          * is enabled. For cards can do hardware encryption, they must do
139          * hardware fragmentation as well. So we don't need a variable
140          * like host_enc_frag. */
141         ieee->host_open_frag = 1;
142         ieee->ieee802_1x = 1;   /* Default to supporting 802.1x */
143
144         INIT_LIST_HEAD(&ieee->crypt_deinit_list);
145         init_timer(&ieee->crypt_deinit_timer);
146         ieee->crypt_deinit_timer.data = (unsigned long)ieee;
147         ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
148         ieee->crypt_quiesced = 0;
149
150         spin_lock_init(&ieee->lock);
151
152         ieee->wpa_enabled = 0;
153         ieee->tkip_countermeasures = 0;
154         ieee->drop_unencrypted = 0;
155         ieee->privacy_invoked = 0;
156
157         return dev;
158
159       failed:
160         if (dev)
161                 free_netdev(dev);
162         return NULL;
163 }
164
165 void free_ieee80211(struct net_device *dev)
166 {
167         struct ieee80211_device *ieee = netdev_priv(dev);
168
169         int i;
170
171         ieee80211_crypt_quiescing(ieee);
172         del_timer_sync(&ieee->crypt_deinit_timer);
173         ieee80211_crypt_deinit_entries(ieee, 1);
174
175         for (i = 0; i < WEP_KEYS; i++) {
176                 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
177                 if (crypt) {
178                         if (crypt->ops) {
179                                 crypt->ops->deinit(crypt->priv);
180                                 module_put(crypt->ops->owner);
181                         }
182                         kfree(crypt);
183                         ieee->crypt[i] = NULL;
184                 }
185         }
186
187         ieee80211_networks_free(ieee);
188         free_netdev(dev);
189 }
190
191 #ifdef CONFIG_IEEE80211_DEBUG
192
193 static int debug = 0;
194 u32 ieee80211_debug_level = 0;
195 struct proc_dir_entry *ieee80211_proc = NULL;
196
197 static int show_debug_level(char *page, char **start, off_t offset,
198                             int count, int *eof, void *data)
199 {
200         return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
201 }
202
203 static int store_debug_level(struct file *file, const char __user * buffer,
204                              unsigned long count, void *data)
205 {
206         char buf[] = "0x00000000\n";
207         unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
208         unsigned long val;
209
210         if (copy_from_user(buf, buffer, len))
211                 return count;
212         buf[len] = 0;
213         if (sscanf(buf, "%li", &val) != 1)
214                 printk(KERN_INFO DRV_NAME
215                        ": %s is not in hex or decimal form.\n", buf);
216         else
217                 ieee80211_debug_level = val;
218
219         return strnlen(buf, len);
220 }
221
222 static int __init ieee80211_init(void)
223 {
224         struct proc_dir_entry *e;
225
226         ieee80211_debug_level = debug;
227         ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
228         if (ieee80211_proc == NULL) {
229                 IEEE80211_ERROR("Unable to create " DRV_NAME
230                                 " proc directory\n");
231                 return -EIO;
232         }
233         e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
234                               ieee80211_proc);
235         if (!e) {
236                 remove_proc_entry(DRV_NAME, proc_net);
237                 ieee80211_proc = NULL;
238                 return -EIO;
239         }
240         e->read_proc = show_debug_level;
241         e->write_proc = store_debug_level;
242         e->data = NULL;
243
244         return 0;
245 }
246
247 static void __exit ieee80211_exit(void)
248 {
249         if (ieee80211_proc) {
250                 remove_proc_entry("debug_level", ieee80211_proc);
251                 remove_proc_entry(DRV_NAME, proc_net);
252                 ieee80211_proc = NULL;
253         }
254 }
255
256 #include <linux/moduleparam.h>
257 module_param(debug, int, 0444);
258 MODULE_PARM_DESC(debug, "debug output mask");
259
260 module_exit(ieee80211_exit);
261 module_init(ieee80211_init);
262 #endif
263
264 const char *escape_essid(const char *essid, u8 essid_len)
265 {
266         static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
267         const char *s = essid;
268         char *d = escaped;
269
270         if (ieee80211_is_empty_essid(essid, essid_len)) {
271                 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
272                 return escaped;
273         }
274
275         essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
276         while (essid_len--) {
277                 if (*s == '\0') {
278                         *d++ = '\\';
279                         *d++ = '0';
280                         s++;
281                 } else {
282                         *d++ = *s++;
283                 }
284         }
285         *d = '\0';
286         return escaped;
287 }
288
289 EXPORT_SYMBOL(alloc_ieee80211);
290 EXPORT_SYMBOL(free_ieee80211);
291 EXPORT_SYMBOL(escape_essid);