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 
56 u32 rt_global_debug_component = COMP_ERR;
57 EXPORT_SYMBOL(rt_global_debug_component);
58 
59 
_setup_timer(struct timer_list * ptimer,void * fun,unsigned long data)60 void _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 
rtllib_networks_allocate(struct rtllib_device * ieee)67 static 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 		printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
77 		       ieee->dev->name);
78 		return -ENOMEM;
79 	}
80 
81 	return 0;
82 }
83 
rtllib_networks_free(struct rtllib_device * ieee)84 static inline void rtllib_networks_free(struct rtllib_device *ieee)
85 {
86 	if (!ieee->networks)
87 		return;
88 	kfree(ieee->networks);
89 	ieee->networks = NULL;
90 }
91 
rtllib_networks_initialize(struct rtllib_device * ieee)92 static inline void rtllib_networks_initialize(struct rtllib_device *ieee)
93 {
94 	int i;
95 
96 	INIT_LIST_HEAD(&ieee->network_free_list);
97 	INIT_LIST_HEAD(&ieee->network_list);
98 	for (i = 0; i < MAX_NETWORK_COUNT; i++)
99 		list_add_tail(&ieee->networks[i].list,
100 			      &ieee->network_free_list);
101 }
102 
alloc_rtllib(int sizeof_priv)103 struct net_device *alloc_rtllib(int sizeof_priv)
104 {
105 	struct rtllib_device *ieee = NULL;
106 	struct net_device *dev;
107 	int i, err;
108 
109 	RTLLIB_DEBUG_INFO("Initializing...\n");
110 
111 	dev = alloc_etherdev(sizeof(struct rtllib_device) + sizeof_priv);
112 	if (!dev) {
113 		RTLLIB_ERROR("Unable to network device.\n");
114 		goto failed;
115 	}
116 	ieee = (struct rtllib_device *)netdev_priv_rsl(dev);
117 	memset(ieee, 0, sizeof(struct rtllib_device)+sizeof_priv);
118 	ieee->dev = dev;
119 
120 	err = rtllib_networks_allocate(ieee);
121 	if (err) {
122 		RTLLIB_ERROR("Unable to allocate beacon storage: %d\n",
123 				err);
124 		goto failed;
125 	}
126 	rtllib_networks_initialize(ieee);
127 
128 
129 	/* Default fragmentation threshold is maximum payload size */
130 	ieee->fts = DEFAULT_FTS;
131 	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
132 	ieee->open_wep = 1;
133 
134 	/* Default to enabling full open WEP with host based encrypt/decrypt */
135 	ieee->host_encrypt = 1;
136 	ieee->host_decrypt = 1;
137 	ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
138 
139 	ieee->rtllib_ap_sec_type = rtllib_ap_sec_type;
140 
141 	spin_lock_init(&ieee->lock);
142 	spin_lock_init(&ieee->wpax_suitlist_lock);
143 	spin_lock_init(&ieee->bw_spinlock);
144 	spin_lock_init(&ieee->reorder_spinlock);
145 	atomic_set(&(ieee->atm_chnlop), 0);
146 	atomic_set(&(ieee->atm_swbw), 0);
147 
148 	/* SAM FIXME */
149 	lib80211_crypt_info_init(&ieee->crypt_info, "RTLLIB", &ieee->lock);
150 
151 	ieee->bHalfNMode = false;
152 	ieee->wpa_enabled = 0;
153 	ieee->tkip_countermeasures = 0;
154 	ieee->drop_unencrypted = 0;
155 	ieee->privacy_invoked = 0;
156 	ieee->ieee802_1x = 1;
157 	ieee->raw_tx = 0;
158 	ieee->hwsec_active = 0;
159 
160 	memset(ieee->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
161 	rtllib_softmac_init(ieee);
162 
163 	ieee->pHTInfo = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL);
164 	if (ieee->pHTInfo == NULL) {
165 		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for HTInfo\n");
166 		return NULL;
167 	}
168 	HTUpdateDefaultSetting(ieee);
169 	HTInitializeHTInfo(ieee);
170 	TSInitialize(ieee);
171 	for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
172 		INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
173 
174 	for (i = 0; i < 17; i++) {
175 		ieee->last_rxseq_num[i] = -1;
176 		ieee->last_rxfrag_num[i] = -1;
177 		ieee->last_packet_time[i] = 0;
178 	}
179 
180 	return dev;
181 
182  failed:
183 	if (dev)
184 		free_netdev(dev);
185 	return NULL;
186 }
187 EXPORT_SYMBOL(alloc_rtllib);
188 
free_rtllib(struct net_device * dev)189 void free_rtllib(struct net_device *dev)
190 {
191 	struct rtllib_device *ieee = (struct rtllib_device *)
192 				      netdev_priv_rsl(dev);
193 
194 	kfree(ieee->pHTInfo);
195 	ieee->pHTInfo = NULL;
196 	rtllib_softmac_free(ieee);
197 
198 	lib80211_crypt_info_free(&ieee->crypt_info);
199 
200 	rtllib_networks_free(ieee);
201 	free_netdev(dev);
202 }
203 EXPORT_SYMBOL(free_rtllib);
204 
205 u32 rtllib_debug_level;
206 static int debug = \
207 			    RTLLIB_DL_ERR
208 			    ;
209 static struct proc_dir_entry *rtllib_proc;
210 
show_debug_level(char * page,char ** start,off_t offset,int count,int * eof,void * data)211 static int show_debug_level(char *page, char **start, off_t offset,
212 			    int count, int *eof, void *data)
213 {
214 	return snprintf(page, count, "0x%08X\n", rtllib_debug_level);
215 }
216 
store_debug_level(struct file * file,const char __user * buffer,unsigned long count,void * data)217 static int store_debug_level(struct file *file, const char __user *buffer,
218 			     unsigned long count, void *data)
219 {
220 	char buf[] = "0x00000000";
221 	unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
222 	char *p = (char *)buf;
223 	unsigned long val;
224 
225 	if (copy_from_user(buf, buffer, len))
226 		return count;
227 	buf[len] = 0;
228 	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
229 		p++;
230 		if (p[0] == 'x' || p[0] == 'X')
231 			p++;
232 		val = simple_strtoul(p, &p, 16);
233 	} else
234 		val = simple_strtoul(p, &p, 10);
235 	if (p == buf)
236 		printk(KERN_INFO DRV_NAME
237 		       ": %s is not in hex or decimal form.\n", buf);
238 	else
239 		rtllib_debug_level = val;
240 
241 	return strnlen(buf, count);
242 }
243 
rtllib_init(void)244 int __init rtllib_init(void)
245 {
246 	struct proc_dir_entry *e;
247 
248 	rtllib_debug_level = debug;
249 	rtllib_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
250 	if (rtllib_proc == NULL) {
251 		RTLLIB_ERROR("Unable to create " DRV_NAME
252 				" proc directory\n");
253 		return -EIO;
254 	}
255 	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
256 			      rtllib_proc);
257 	if (!e) {
258 		remove_proc_entry(DRV_NAME, init_net.proc_net);
259 		rtllib_proc = NULL;
260 		return -EIO;
261 	}
262 	e->read_proc = show_debug_level;
263 	e->write_proc = store_debug_level;
264 	e->data = NULL;
265 
266 	return 0;
267 }
268 
rtllib_exit(void)269 void __exit rtllib_exit(void)
270 {
271 	if (rtllib_proc) {
272 		remove_proc_entry("debug_level", rtllib_proc);
273 		remove_proc_entry(DRV_NAME, init_net.proc_net);
274 		rtllib_proc = NULL;
275 	}
276 }
277 
278 module_init(rtllib_init);
279 module_exit(rtllib_exit);
280 
281 MODULE_LICENSE("GPL");
282