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 		LIBIPW_ERROR("Unable to allocate network device.\n");
155 		goto failed;
156 	}
157 	ieee = netdev_priv(dev);
158 
159 	ieee->dev = dev;
160 
161 	if (!monitor) {
162 		ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
163 		if (!ieee->wdev.wiphy) {
164 			LIBIPW_ERROR("Unable to allocate wiphy.\n");
165 			goto failed_free_netdev;
166 		}
167 
168 		ieee->dev->ieee80211_ptr = &ieee->wdev;
169 		ieee->wdev.iftype = NL80211_IFTYPE_STATION;
170 
171 		/* Fill-out wiphy structure bits we know...  Not enough info
172 		   here to call set_wiphy_dev or set MAC address or channel info
173 		   -- have to do that in ->ndo_init... */
174 		ieee->wdev.wiphy->privid = libipw_wiphy_privid;
175 
176 		ieee->wdev.wiphy->max_scan_ssids = 1;
177 		ieee->wdev.wiphy->max_scan_ie_len = 0;
178 		ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
179 						| BIT(NL80211_IFTYPE_ADHOC);
180 	}
181 
182 	err = libipw_networks_allocate(ieee);
183 	if (err) {
184 		LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
185 		goto failed_free_wiphy;
186 	}
187 	libipw_networks_initialize(ieee);
188 
189 	/* Default fragmentation threshold is maximum payload size */
190 	ieee->fts = DEFAULT_FTS;
191 	ieee->rts = DEFAULT_FTS;
192 	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
193 	ieee->open_wep = 1;
194 
195 	/* Default to enabling full open WEP with host based encrypt/decrypt */
196 	ieee->host_encrypt = 1;
197 	ieee->host_decrypt = 1;
198 	ieee->host_mc_decrypt = 1;
199 
200 	/* Host fragmentation in Open mode. Default is enabled.
201 	 * Note: host fragmentation is always enabled if host encryption
202 	 * is enabled. For cards can do hardware encryption, they must do
203 	 * hardware fragmentation as well. So we don't need a variable
204 	 * like host_enc_frag. */
205 	ieee->host_open_frag = 1;
206 	ieee->ieee802_1x = 1;	/* Default to supporting 802.1x */
207 
208 	spin_lock_init(&ieee->lock);
209 
210 	lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
211 
212 	ieee->wpa_enabled = 0;
213 	ieee->drop_unencrypted = 0;
214 	ieee->privacy_invoked = 0;
215 
216 	return dev;
217 
218 failed_free_wiphy:
219 	if (!monitor)
220 		wiphy_free(ieee->wdev.wiphy);
221 failed_free_netdev:
222 	free_netdev(dev);
223 failed:
224 	return NULL;
225 }
226 EXPORT_SYMBOL(alloc_libipw);
227 
free_libipw(struct net_device * dev,int monitor)228 void free_libipw(struct net_device *dev, int monitor)
229 {
230 	struct libipw_device *ieee = netdev_priv(dev);
231 
232 	lib80211_crypt_info_free(&ieee->crypt_info);
233 
234 	libipw_networks_free(ieee);
235 
236 	/* free cfg80211 resources */
237 	if (!monitor)
238 		wiphy_free(ieee->wdev.wiphy);
239 
240 	free_netdev(dev);
241 }
242 EXPORT_SYMBOL(free_libipw);
243 
244 #ifdef CONFIG_LIBIPW_DEBUG
245 
246 static int debug = 0;
247 u32 libipw_debug_level = 0;
248 EXPORT_SYMBOL_GPL(libipw_debug_level);
249 static struct proc_dir_entry *libipw_proc = NULL;
250 
debug_level_proc_show(struct seq_file * m,void * v)251 static int debug_level_proc_show(struct seq_file *m, void *v)
252 {
253 	seq_printf(m, "0x%08X\n", libipw_debug_level);
254 	return 0;
255 }
256 
debug_level_proc_open(struct inode * inode,struct file * file)257 static int debug_level_proc_open(struct inode *inode, struct file *file)
258 {
259 	return single_open(file, debug_level_proc_show, NULL);
260 }
261 
debug_level_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * pos)262 static ssize_t debug_level_proc_write(struct file *file,
263 		const char __user *buffer, size_t count, loff_t *pos)
264 {
265 	char buf[] = "0x00000000\n";
266 	size_t len = min(sizeof(buf) - 1, count);
267 	unsigned long val;
268 
269 	if (copy_from_user(buf, buffer, len))
270 		return count;
271 	buf[len] = 0;
272 	if (sscanf(buf, "%li", &val) != 1)
273 		printk(KERN_INFO DRV_NAME
274 		       ": %s is not in hex or decimal form.\n", buf);
275 	else
276 		libipw_debug_level = val;
277 
278 	return strnlen(buf, len);
279 }
280 
281 static const struct file_operations debug_level_proc_fops = {
282 	.owner		= THIS_MODULE,
283 	.open		= debug_level_proc_open,
284 	.read		= seq_read,
285 	.llseek		= seq_lseek,
286 	.release	= single_release,
287 	.write		= debug_level_proc_write,
288 };
289 #endif				/* CONFIG_LIBIPW_DEBUG */
290 
libipw_init(void)291 static int __init libipw_init(void)
292 {
293 #ifdef CONFIG_LIBIPW_DEBUG
294 	struct proc_dir_entry *e;
295 
296 	libipw_debug_level = debug;
297 	libipw_proc = proc_mkdir(DRV_PROCNAME, init_net.proc_net);
298 	if (libipw_proc == NULL) {
299 		LIBIPW_ERROR("Unable to create " DRV_PROCNAME
300 				" proc directory\n");
301 		return -EIO;
302 	}
303 	e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
304 			&debug_level_proc_fops);
305 	if (!e) {
306 		remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
307 		libipw_proc = NULL;
308 		return -EIO;
309 	}
310 #endif				/* CONFIG_LIBIPW_DEBUG */
311 
312 	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
313 	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
314 
315 	return 0;
316 }
317 
libipw_exit(void)318 static void __exit libipw_exit(void)
319 {
320 #ifdef CONFIG_LIBIPW_DEBUG
321 	if (libipw_proc) {
322 		remove_proc_entry("debug_level", libipw_proc);
323 		remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
324 		libipw_proc = NULL;
325 	}
326 #endif				/* CONFIG_LIBIPW_DEBUG */
327 }
328 
329 #ifdef CONFIG_LIBIPW_DEBUG
330 #include <linux/moduleparam.h>
331 module_param(debug, int, 0444);
332 MODULE_PARM_DESC(debug, "debug output mask");
333 #endif				/* CONFIG_LIBIPW_DEBUG */
334 
335 module_exit(libipw_exit);
336 module_init(libipw_init);
337