Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Mar 24-27, 2025, special US time zones
Register
Loading...
Note: File does not exist in v6.13.7.
  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
 61MODULE_VERSION(DRV_VERSION);
 62MODULE_DESCRIPTION(DRV_DESCRIPTION);
 63MODULE_AUTHOR(DRV_COPYRIGHT);
 64MODULE_LICENSE("GPL");
 65
 66static struct cfg80211_ops libipw_config_ops = { };
 67static void *libipw_wiphy_privid = &libipw_wiphy_privid;
 68
 69static 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
 87void 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
 98static 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
109void 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}
122EXPORT_SYMBOL(libipw_networks_age);
123
124static 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
135int 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}
142EXPORT_SYMBOL(libipw_change_mtu);
143
144struct 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
218failed_free_wiphy:
219	if (!monitor)
220		wiphy_free(ieee->wdev.wiphy);
221failed_free_netdev:
222	free_netdev(dev);
223failed:
224	return NULL;
225}
226EXPORT_SYMBOL(alloc_libipw);
227
228void 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}
242EXPORT_SYMBOL(free_libipw);
243
244#ifdef CONFIG_LIBIPW_DEBUG
245
246static int debug = 0;
247u32 libipw_debug_level = 0;
248EXPORT_SYMBOL_GPL(libipw_debug_level);
249static struct proc_dir_entry *libipw_proc = NULL;
250
251static 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
257static int debug_level_proc_open(struct inode *inode, struct file *file)
258{
259	return single_open(file, debug_level_proc_show, NULL);
260}
261
262static 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
281static 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
291static 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
318static 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>
331module_param(debug, int, 0444);
332MODULE_PARM_DESC(debug, "debug output mask");
333#endif				/* CONFIG_LIBIPW_DEBUG */
334
335module_exit(libipw_exit);
336module_init(libipw_init);