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   <j@w1.fi>
9   Copyright (c) 2002-2003, Jouni Malinen <j@w1.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   Intel Linux Wireless <ilw@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/net_namespace.h>
51 #include <net/arp.h>
52 
53 #include "libipw.h"
54 
55 #define DRV_DESCRIPTION "802.11 data/management/control stack"
56 #define DRV_NAME        "libipw"
57 #define DRV_PROCNAME	"ieee80211"
58 #define DRV_VERSION	LIBIPW_VERSION
59 #define DRV_COPYRIGHT   "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
60 
61 MODULE_VERSION(DRV_VERSION);
62 MODULE_DESCRIPTION(DRV_DESCRIPTION);
63 MODULE_AUTHOR(DRV_COPYRIGHT);
64 MODULE_LICENSE("GPL");
65 
66 static struct cfg80211_ops libipw_config_ops = { };
67 static void *libipw_wiphy_privid = &libipw_wiphy_privid;
68 
libipw_networks_allocate(struct libipw_device * ieee)69 static int libipw_networks_allocate(struct libipw_device *ieee)
70 {
71 	int i, j;
72 
73 	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
74 		ieee->networks[i] = kzalloc(sizeof(struct libipw_network),
75 					    GFP_KERNEL);
76 		if (!ieee->networks[i]) {
77 			LIBIPW_ERROR("Out of memory allocating beacons\n");
78 			for (j = 0; j < i; j++)
79 				kfree(ieee->networks[j]);
80 			return -ENOMEM;
81 		}
82 	}
83 
84 	return 0;
85 }
86 
libipw_network_reset(struct libipw_network * network)87 void libipw_network_reset(struct libipw_network *network)
88 {
89 	if (!network)
90 		return;
91 
92 	if (network->ibss_dfs) {
93 		kfree(network->ibss_dfs);
94 		network->ibss_dfs = NULL;
95 	}
96 }
97 
libipw_networks_free(struct libipw_device * ieee)98 static inline void libipw_networks_free(struct libipw_device *ieee)
99 {
100 	int i;
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 		kfree(ieee->networks[i]);
106 	}
107 }
108 
libipw_networks_age(struct libipw_device * ieee,unsigned long age_secs)109 void libipw_networks_age(struct libipw_device *ieee,
110                             unsigned long age_secs)
111 {
112 	struct libipw_network *network = NULL;
113 	unsigned long flags;
114 	unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
115 
116 	spin_lock_irqsave(&ieee->lock, flags);
117 	list_for_each_entry(network, &ieee->network_list, list) {
118 		network->last_scanned -= age_jiffies;
119 	}
120 	spin_unlock_irqrestore(&ieee->lock, flags);
121 }
122 EXPORT_SYMBOL(libipw_networks_age);
123 
libipw_networks_initialize(struct libipw_device * ieee)124 static void libipw_networks_initialize(struct libipw_device *ieee)
125 {
126 	int i;
127 
128 	INIT_LIST_HEAD(&ieee->network_free_list);
129 	INIT_LIST_HEAD(&ieee->network_list);
130 	for (i = 0; i < MAX_NETWORK_COUNT; i++)
131 		list_add_tail(&ieee->networks[i]->list,
132 			      &ieee->network_free_list);
133 }
134 
libipw_change_mtu(struct net_device * dev,int new_mtu)135 int libipw_change_mtu(struct net_device *dev, int new_mtu)
136 {
137 	if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
138 		return -EINVAL;
139 	dev->mtu = new_mtu;
140 	return 0;
141 }
142 EXPORT_SYMBOL(libipw_change_mtu);
143 
alloc_libipw(int sizeof_priv,int monitor)144 struct net_device *alloc_libipw(int sizeof_priv, int monitor)
145 {
146 	struct libipw_device *ieee;
147 	struct net_device *dev;
148 	int err;
149 
150 	LIBIPW_DEBUG_INFO("Initializing...\n");
151 
152 	dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
153 	if (!dev)
154 		goto failed;
155 
156 	ieee = netdev_priv(dev);
157 
158 	ieee->dev = dev;
159 
160 	if (!monitor) {
161 		ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
162 		if (!ieee->wdev.wiphy) {
163 			LIBIPW_ERROR("Unable to allocate wiphy.\n");
164 			goto failed_free_netdev;
165 		}
166 
167 		ieee->dev->ieee80211_ptr = &ieee->wdev;
168 		ieee->wdev.iftype = NL80211_IFTYPE_STATION;
169 
170 		/* Fill-out wiphy structure bits we know...  Not enough info
171 		   here to call set_wiphy_dev or set MAC address or channel info
172 		   -- have to do that in ->ndo_init... */
173 		ieee->wdev.wiphy->privid = libipw_wiphy_privid;
174 
175 		ieee->wdev.wiphy->max_scan_ssids = 1;
176 		ieee->wdev.wiphy->max_scan_ie_len = 0;
177 		ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
178 						| BIT(NL80211_IFTYPE_ADHOC);
179 	}
180 
181 	err = libipw_networks_allocate(ieee);
182 	if (err) {
183 		LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
184 		goto failed_free_wiphy;
185 	}
186 	libipw_networks_initialize(ieee);
187 
188 	/* Default fragmentation threshold is maximum payload size */
189 	ieee->fts = DEFAULT_FTS;
190 	ieee->rts = DEFAULT_FTS;
191 	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
192 	ieee->open_wep = 1;
193 
194 	/* Default to enabling full open WEP with host based encrypt/decrypt */
195 	ieee->host_encrypt = 1;
196 	ieee->host_decrypt = 1;
197 	ieee->host_mc_decrypt = 1;
198 
199 	/* Host fragmentation in Open mode. Default is enabled.
200 	 * Note: host fragmentation is always enabled if host encryption
201 	 * is enabled. For cards can do hardware encryption, they must do
202 	 * hardware fragmentation as well. So we don't need a variable
203 	 * like host_enc_frag. */
204 	ieee->host_open_frag = 1;
205 	ieee->ieee802_1x = 1;	/* Default to supporting 802.1x */
206 
207 	spin_lock_init(&ieee->lock);
208 
209 	lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
210 
211 	ieee->wpa_enabled = 0;
212 	ieee->drop_unencrypted = 0;
213 	ieee->privacy_invoked = 0;
214 
215 	return dev;
216 
217 failed_free_wiphy:
218 	if (!monitor)
219 		wiphy_free(ieee->wdev.wiphy);
220 failed_free_netdev:
221 	free_netdev(dev);
222 failed:
223 	return NULL;
224 }
225 EXPORT_SYMBOL(alloc_libipw);
226 
free_libipw(struct net_device * dev,int monitor)227 void free_libipw(struct net_device *dev, int monitor)
228 {
229 	struct libipw_device *ieee = netdev_priv(dev);
230 
231 	lib80211_crypt_info_free(&ieee->crypt_info);
232 
233 	libipw_networks_free(ieee);
234 
235 	/* free cfg80211 resources */
236 	if (!monitor)
237 		wiphy_free(ieee->wdev.wiphy);
238 
239 	free_netdev(dev);
240 }
241 EXPORT_SYMBOL(free_libipw);
242 
243 #ifdef CONFIG_LIBIPW_DEBUG
244 
245 static int debug = 0;
246 u32 libipw_debug_level = 0;
247 EXPORT_SYMBOL_GPL(libipw_debug_level);
248 static struct proc_dir_entry *libipw_proc = NULL;
249 
debug_level_proc_show(struct seq_file * m,void * v)250 static int debug_level_proc_show(struct seq_file *m, void *v)
251 {
252 	seq_printf(m, "0x%08X\n", libipw_debug_level);
253 	return 0;
254 }
255 
debug_level_proc_open(struct inode * inode,struct file * file)256 static int debug_level_proc_open(struct inode *inode, struct file *file)
257 {
258 	return single_open(file, debug_level_proc_show, NULL);
259 }
260 
debug_level_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * pos)261 static ssize_t debug_level_proc_write(struct file *file,
262 		const char __user *buffer, size_t count, loff_t *pos)
263 {
264 	char buf[] = "0x00000000\n";
265 	size_t len = min(sizeof(buf) - 1, count);
266 	unsigned long val;
267 
268 	if (copy_from_user(buf, buffer, len))
269 		return count;
270 	buf[len] = 0;
271 	if (sscanf(buf, "%li", &val) != 1)
272 		printk(KERN_INFO DRV_NAME
273 		       ": %s is not in hex or decimal form.\n", buf);
274 	else
275 		libipw_debug_level = val;
276 
277 	return strnlen(buf, len);
278 }
279 
280 static const struct file_operations debug_level_proc_fops = {
281 	.owner		= THIS_MODULE,
282 	.open		= debug_level_proc_open,
283 	.read		= seq_read,
284 	.llseek		= seq_lseek,
285 	.release	= single_release,
286 	.write		= debug_level_proc_write,
287 };
288 #endif				/* CONFIG_LIBIPW_DEBUG */
289 
libipw_init(void)290 static int __init libipw_init(void)
291 {
292 #ifdef CONFIG_LIBIPW_DEBUG
293 	struct proc_dir_entry *e;
294 
295 	libipw_debug_level = debug;
296 	libipw_proc = proc_mkdir(DRV_PROCNAME, init_net.proc_net);
297 	if (libipw_proc == NULL) {
298 		LIBIPW_ERROR("Unable to create " DRV_PROCNAME
299 				" proc directory\n");
300 		return -EIO;
301 	}
302 	e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
303 			&debug_level_proc_fops);
304 	if (!e) {
305 		remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
306 		libipw_proc = NULL;
307 		return -EIO;
308 	}
309 #endif				/* CONFIG_LIBIPW_DEBUG */
310 
311 	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
312 	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
313 
314 	return 0;
315 }
316 
libipw_exit(void)317 static void __exit libipw_exit(void)
318 {
319 #ifdef CONFIG_LIBIPW_DEBUG
320 	if (libipw_proc) {
321 		remove_proc_entry("debug_level", libipw_proc);
322 		remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
323 		libipw_proc = NULL;
324 	}
325 #endif				/* CONFIG_LIBIPW_DEBUG */
326 }
327 
328 #ifdef CONFIG_LIBIPW_DEBUG
329 #include <linux/moduleparam.h>
330 module_param(debug, int, 0444);
331 MODULE_PARM_DESC(debug, "debug output mask");
332 #endif				/* CONFIG_LIBIPW_DEBUG */
333 
334 module_exit(libipw_exit);
335 module_init(libipw_init);
336