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