Linux Audio

Check our new training course

Linux kernel drivers training

May 6-19, 2025
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		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
217failed_free_wiphy:
218	if (!monitor)
219		wiphy_free(ieee->wdev.wiphy);
220failed_free_netdev:
221	free_netdev(dev);
222failed:
223	return NULL;
224}
225EXPORT_SYMBOL(alloc_libipw);
226
227void 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}
241EXPORT_SYMBOL(free_libipw);
242
243#ifdef CONFIG_LIBIPW_DEBUG
244
245static int debug = 0;
246u32 libipw_debug_level = 0;
247EXPORT_SYMBOL_GPL(libipw_debug_level);
248static struct proc_dir_entry *libipw_proc = NULL;
249
250static 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
256static int debug_level_proc_open(struct inode *inode, struct file *file)
257{
258	return single_open(file, debug_level_proc_show, NULL);
259}
260
261static 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
280static 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
290static 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
317static 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>
330module_param(debug, int, 0444);
331MODULE_PARM_DESC(debug, "debug output mask");
332#endif				/* CONFIG_LIBIPW_DEBUG */
333
334module_exit(libipw_exit);
335module_init(libipw_init);