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