1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/compiler.h>
34
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/pci.h>
44#include <linux/proc_fs.h>
45#include <linux/skbuff.h>
46#include <linux/slab.h>
47#include <linux/tcp.h>
48#include <linux/types.h>
49#include <linux/version.h>
50#include <linux/wireless.h>
51#include <linux/etherdevice.h>
52#include <asm/uaccess.h>
53#include <net/arp.h>
54
55#include "ieee80211.h"
56
57MODULE_DESCRIPTION("802.11 data/management/control stack");
58MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
59MODULE_LICENSE("GPL");
60
61#define DRV_NAME "ieee80211"
62
63static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
64{
65 if (ieee->networks)
66 return 0;
67
68 ieee->networks = kmalloc(
69 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
83static 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
91static 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, &ieee->network_free_list);
99}
100
101
102struct net_device *alloc_ieee80211(int sizeof_priv)
103{
104 struct ieee80211_device *ieee;
105 struct net_device *dev;
106 int i,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
116 ieee = netdev_priv(dev);
117 memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv);
118 ieee->dev = dev;
119
120 err = ieee80211_networks_allocate(ieee);
121 if (err) {
122 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
123 err);
124 goto failed;
125 }
126 ieee80211_networks_initialize(ieee);
127
128
129
130 ieee->fts = DEFAULT_FTS;
131 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
132 ieee->open_wep = 1;
133
134
135 ieee->host_encrypt = 1;
136 ieee->host_decrypt = 1;
137 ieee->ieee802_1x = 1;
138
139 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
140 init_timer(&ieee->crypt_deinit_timer);
141 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
142 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
143
144 spin_lock_init(&ieee->lock);
145 spin_lock_init(&ieee->wpax_suitlist_lock);
146 spin_lock_init(&ieee->bw_spinlock);
147 spin_lock_init(&ieee->reorder_spinlock);
148
149 atomic_set(&(ieee->atm_chnlop), 0);
150 atomic_set(&(ieee->atm_swbw), 0);
151
152 ieee->wpax_type_set = 0;
153 ieee->wpa_enabled = 0;
154 ieee->tkip_countermeasures = 0;
155 ieee->drop_unencrypted = 0;
156 ieee->privacy_invoked = 0;
157 ieee->ieee802_1x = 1;
158 ieee->raw_tx = 0;
159
160 ieee->hwsec_active = 0;
161
162 ieee80211_softmac_init(ieee);
163
164 ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
165 if (ieee->pHTInfo == NULL)
166 {
167 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
168 return NULL;
169 }
170 HTUpdateDefaultSetting(ieee);
171 HTInitializeHTInfo(ieee);
172 TSInitialize(ieee);
173
174 for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
175 INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
176
177 for (i = 0; i < 17; i++) {
178 ieee->last_rxseq_num[i] = -1;
179 ieee->last_rxfrag_num[i] = -1;
180 ieee->last_packet_time[i] = 0;
181 }
182
183
184 ieee80211_tkip_null();
185 ieee80211_wep_null();
186 ieee80211_ccmp_null();
187
188 return dev;
189
190 failed:
191 if (dev)
192 free_netdev(dev);
193
194 return NULL;
195}
196
197
198void free_ieee80211(struct net_device *dev)
199{
200 struct ieee80211_device *ieee = netdev_priv(dev);
201 int i;
202
203
204#if 1
205 if (ieee->pHTInfo != NULL)
206 {
207 kfree(ieee->pHTInfo);
208 ieee->pHTInfo = NULL;
209 }
210#endif
211 RemoveAllTS(ieee);
212 ieee80211_softmac_free(ieee);
213 del_timer_sync(&ieee->crypt_deinit_timer);
214 ieee80211_crypt_deinit_entries(ieee, 1);
215
216 for (i = 0; i < WEP_KEYS; i++) {
217 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
218 if (crypt) {
219 if (crypt->ops)
220 crypt->ops->deinit(crypt->priv);
221 kfree(crypt);
222 ieee->crypt[i] = NULL;
223 }
224 }
225
226 ieee80211_networks_free(ieee);
227 free_netdev(dev);
228}
229
230#ifdef CONFIG_IEEE80211_DEBUG
231
232u32 ieee80211_debug_level = 0;
233static int debug = \
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 IEEE80211_DL_ERR
252 ;
253struct proc_dir_entry *ieee80211_proc = NULL;
254
255static int show_debug_level(char *page, char **start, off_t offset,
256 int count, int *eof, void *data)
257{
258 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
259}
260
261static int store_debug_level(struct file *file, const char *buffer,
262 unsigned long count, void *data)
263{
264 char buf[] = "0x00000000";
265 unsigned long len = min(sizeof(buf) - 1, count);
266 char *p = (char *)buf;
267 unsigned long val;
268
269 if (copy_from_user(buf, buffer, len))
270 return count;
271 buf[len] = 0;
272 if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
273 p++;
274 if (p[0] == 'x' || p[0] == 'X')
275 p++;
276 val = simple_strtoul(p, &p, 16);
277 } else
278 val = simple_strtoul(p, &p, 10);
279 if (p == buf)
280 printk(KERN_INFO DRV_NAME
281 ": %s is not in hex or decimal form.\n", buf);
282 else
283 ieee80211_debug_level = val;
284
285 return strnlen(buf, count);
286}
287
288int __init ieee80211_debug_init(void)
289{
290 struct proc_dir_entry *e;
291
292 ieee80211_debug_level = debug;
293
294 ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
295 if (ieee80211_proc == NULL) {
296 IEEE80211_ERROR("Unable to create " DRV_NAME
297 " proc directory\n");
298 return -EIO;
299 }
300 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
301 ieee80211_proc);
302 if (!e) {
303 remove_proc_entry(DRV_NAME, init_net.proc_net);
304 ieee80211_proc = NULL;
305 return -EIO;
306 }
307 e->read_proc = show_debug_level;
308 e->write_proc = store_debug_level;
309 e->data = NULL;
310
311 return 0;
312}
313
314void __exit ieee80211_debug_exit(void)
315{
316 if (ieee80211_proc) {
317 remove_proc_entry("debug_level", ieee80211_proc);
318 remove_proc_entry(DRV_NAME, init_net.proc_net);
319 ieee80211_proc = NULL;
320 }
321}
322
323#include <linux/moduleparam.h>
324module_param(debug, int, 0444);
325MODULE_PARM_DESC(debug, "debug output mask");
326#endif
327