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