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/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/pci.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 <linux/uaccess.h>
51#include <net/arp.h>
52
53#include "rtllib.h"
54
55
56u32 rt_global_debug_component = COMP_ERR;
57EXPORT_SYMBOL(rt_global_debug_component);
58
59
60void _setup_timer(struct timer_list *ptimer, void *fun, unsigned long data)
61{
62	ptimer->function = fun;
63	ptimer->data = data;
64	init_timer(ptimer);
65}
66
67static inline int rtllib_networks_allocate(struct rtllib_device *ieee)
68{
69	if (ieee->networks)
70		return 0;
71
72	ieee->networks = kzalloc(
73		MAX_NETWORK_COUNT * sizeof(struct rtllib_network),
74		GFP_KERNEL);
75	if (!ieee->networks)
76		return -ENOMEM;
77
78	return 0;
79}
80
81static inline void rtllib_networks_free(struct rtllib_device *ieee)
82{
83	if (!ieee->networks)
84		return;
85	kfree(ieee->networks);
86	ieee->networks = NULL;
87}
88
89static inline void rtllib_networks_initialize(struct rtllib_device *ieee)
90{
91	int i;
92
93	INIT_LIST_HEAD(&ieee->network_free_list);
94	INIT_LIST_HEAD(&ieee->network_list);
95	for (i = 0; i < MAX_NETWORK_COUNT; i++)
96		list_add_tail(&ieee->networks[i].list,
97			      &ieee->network_free_list);
98}
99
100struct net_device *alloc_rtllib(int sizeof_priv)
101{
102	struct rtllib_device *ieee = NULL;
103	struct net_device *dev;
104	int i, err;
105
106	RTLLIB_DEBUG_INFO("Initializing...\n");
107
108	dev = alloc_etherdev(sizeof(struct rtllib_device) + sizeof_priv);
109	if (!dev) {
110		RTLLIB_ERROR("Unable to network device.\n");
111		return NULL;
112	}
113	ieee = (struct rtllib_device *)netdev_priv_rsl(dev);
114	memset(ieee, 0, sizeof(struct rtllib_device)+sizeof_priv);
115	ieee->dev = dev;
116
117	err = rtllib_networks_allocate(ieee);
118	if (err) {
119		RTLLIB_ERROR("Unable to allocate beacon storage: %d\n",
120				err);
121		goto failed;
122	}
123	rtllib_networks_initialize(ieee);
124
125
126	/* Default fragmentation threshold is maximum payload size */
127	ieee->fts = DEFAULT_FTS;
128	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
129	ieee->open_wep = 1;
130
131	/* Default to enabling full open WEP with host based encrypt/decrypt */
132	ieee->host_encrypt = 1;
133	ieee->host_decrypt = 1;
134	ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
135
136	ieee->rtllib_ap_sec_type = rtllib_ap_sec_type;
137
138	spin_lock_init(&ieee->lock);
139	spin_lock_init(&ieee->wpax_suitlist_lock);
140	spin_lock_init(&ieee->bw_spinlock);
141	spin_lock_init(&ieee->reorder_spinlock);
142	atomic_set(&(ieee->atm_chnlop), 0);
143	atomic_set(&(ieee->atm_swbw), 0);
144
145	/* SAM FIXME */
146	lib80211_crypt_info_init(&ieee->crypt_info, "RTLLIB", &ieee->lock);
147
148	ieee->bHalfNMode = false;
149	ieee->wpa_enabled = 0;
150	ieee->tkip_countermeasures = 0;
151	ieee->drop_unencrypted = 0;
152	ieee->privacy_invoked = 0;
153	ieee->ieee802_1x = 1;
154	ieee->raw_tx = 0;
155	ieee->hwsec_active = 0;
156
157	memset(ieee->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
158	rtllib_softmac_init(ieee);
159
160	ieee->pHTInfo = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL);
161	if (ieee->pHTInfo == NULL)
162		return NULL;
163
164	HTUpdateDefaultSetting(ieee);
165	HTInitializeHTInfo(ieee);
166	TSInitialize(ieee);
167	for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
168		INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
169
170	for (i = 0; i < 17; i++) {
171		ieee->last_rxseq_num[i] = -1;
172		ieee->last_rxfrag_num[i] = -1;
173		ieee->last_packet_time[i] = 0;
174	}
175
176	return dev;
177
178 failed:
179	free_netdev(dev);
180	return NULL;
181}
182EXPORT_SYMBOL(alloc_rtllib);
183
184void free_rtllib(struct net_device *dev)
185{
186	struct rtllib_device *ieee = (struct rtllib_device *)
187				      netdev_priv_rsl(dev);
188
189	kfree(ieee->pHTInfo);
190	ieee->pHTInfo = NULL;
191	rtllib_softmac_free(ieee);
192
193	lib80211_crypt_info_free(&ieee->crypt_info);
194
195	rtllib_networks_free(ieee);
196	free_netdev(dev);
197}
198EXPORT_SYMBOL(free_rtllib);
199
200u32 rtllib_debug_level;
201static int debug = RTLLIB_DL_ERR;
202static struct proc_dir_entry *rtllib_proc;
203
204static int show_debug_level(struct seq_file *m, void *v)
205{
206	seq_printf(m, "0x%08X\n", rtllib_debug_level);
207
208	return 0;
209}
210
211static ssize_t write_debug_level(struct file *file, const char __user *buffer,
212			     size_t count, loff_t *ppos)
213{
214	unsigned long val;
215	int err = kstrtoul_from_user(buffer, count, 0, &val);
216
217	if (err)
218		return err;
219	rtllib_debug_level = val;
220	return count;
221}
222
223static int open_debug_level(struct inode *inode, struct file *file)
224{
225	return single_open(file, show_debug_level, NULL);
226}
227
228static const struct file_operations fops = {
229	.open = open_debug_level,
230	.read = seq_read,
231	.llseek = seq_lseek,
232	.write = write_debug_level,
233	.release = single_release,
234};
235
236static int __init rtllib_init(void)
237{
238	struct proc_dir_entry *e;
239
240	rtllib_debug_level = debug;
241	rtllib_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
242	if (rtllib_proc == NULL) {
243		RTLLIB_ERROR("Unable to create " DRV_NAME
244				" proc directory\n");
245		return -EIO;
246	}
247	e = proc_create("debug_level", S_IRUGO | S_IWUSR, rtllib_proc, &fops);
248	if (!e) {
249		remove_proc_entry(DRV_NAME, init_net.proc_net);
250		rtllib_proc = NULL;
251		return -EIO;
252	}
253	return 0;
254}
255
256static void __exit rtllib_exit(void)
257{
258	if (rtllib_proc) {
259		remove_proc_entry("debug_level", rtllib_proc);
260		remove_proc_entry(DRV_NAME, init_net.proc_net);
261		rtllib_proc = NULL;
262	}
263}
264
265module_init(rtllib_init);
266module_exit(rtllib_exit);
267
268MODULE_LICENSE("GPL");
269