Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/*******************************************************************************
3
4 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
5
6 Portions of this file are based on the WEP enablement code provided by the
7 Host AP project hostap-drivers v0.1.3
8 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
9 <j@w1.fi>
10 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
11
12
13 Contact Information:
14 Intel Linux Wireless <ilw@linux.intel.com>
15 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
16
17*******************************************************************************/
18
19#include <linux/compiler.h>
20#include <linux/errno.h>
21#include <linux/if_arp.h>
22#include <linux/in6.h>
23#include <linux/in.h>
24#include <linux/ip.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/netdevice.h>
28#include <linux/proc_fs.h>
29#include <linux/skbuff.h>
30#include <linux/slab.h>
31#include <linux/tcp.h>
32#include <linux/types.h>
33#include <linux/wireless.h>
34#include <linux/etherdevice.h>
35#include <linux/uaccess.h>
36#include <net/net_namespace.h>
37#include <net/arp.h>
38
39#include "libipw.h"
40
41#define DRV_DESCRIPTION "802.11 data/management/control stack"
42#define DRV_NAME "libipw"
43#define DRV_PROCNAME "ieee80211"
44#define DRV_VERSION LIBIPW_VERSION
45#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
46
47MODULE_VERSION(DRV_VERSION);
48MODULE_DESCRIPTION(DRV_DESCRIPTION);
49MODULE_AUTHOR(DRV_COPYRIGHT);
50MODULE_LICENSE("GPL");
51
52static struct cfg80211_ops libipw_config_ops = { };
53static void *libipw_wiphy_privid = &libipw_wiphy_privid;
54
55static int libipw_networks_allocate(struct libipw_device *ieee)
56{
57 int i, j;
58
59 for (i = 0; i < MAX_NETWORK_COUNT; i++) {
60 ieee->networks[i] = kzalloc(sizeof(struct libipw_network),
61 GFP_KERNEL);
62 if (!ieee->networks[i]) {
63 LIBIPW_ERROR("Out of memory allocating beacons\n");
64 for (j = 0; j < i; j++)
65 kfree(ieee->networks[j]);
66 return -ENOMEM;
67 }
68 }
69
70 return 0;
71}
72
73static inline void libipw_networks_free(struct libipw_device *ieee)
74{
75 int i;
76
77 for (i = 0; i < MAX_NETWORK_COUNT; i++)
78 kfree(ieee->networks[i]);
79}
80
81void libipw_networks_age(struct libipw_device *ieee,
82 unsigned long age_secs)
83{
84 struct libipw_network *network = NULL;
85 unsigned long flags;
86 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
87
88 spin_lock_irqsave(&ieee->lock, flags);
89 list_for_each_entry(network, &ieee->network_list, list) {
90 network->last_scanned -= age_jiffies;
91 }
92 spin_unlock_irqrestore(&ieee->lock, flags);
93}
94EXPORT_SYMBOL(libipw_networks_age);
95
96static void libipw_networks_initialize(struct libipw_device *ieee)
97{
98 int i;
99
100 INIT_LIST_HEAD(&ieee->network_free_list);
101 INIT_LIST_HEAD(&ieee->network_list);
102 for (i = 0; i < MAX_NETWORK_COUNT; i++)
103 list_add_tail(&ieee->networks[i]->list,
104 &ieee->network_free_list);
105}
106
107struct net_device *alloc_libipw(int sizeof_priv, int monitor)
108{
109 struct libipw_device *ieee;
110 struct net_device *dev;
111 int err;
112
113 LIBIPW_DEBUG_INFO("Initializing...\n");
114
115 dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
116 if (!dev)
117 goto failed;
118
119 ieee = netdev_priv(dev);
120
121 ieee->dev = dev;
122
123 if (!monitor) {
124 ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
125 if (!ieee->wdev.wiphy) {
126 LIBIPW_ERROR("Unable to allocate wiphy.\n");
127 goto failed_free_netdev;
128 }
129
130 ieee->dev->ieee80211_ptr = &ieee->wdev;
131 ieee->wdev.iftype = NL80211_IFTYPE_STATION;
132
133 /* Fill-out wiphy structure bits we know... Not enough info
134 here to call set_wiphy_dev or set MAC address or channel info
135 -- have to do that in ->ndo_init... */
136 ieee->wdev.wiphy->privid = libipw_wiphy_privid;
137
138 ieee->wdev.wiphy->max_scan_ssids = 1;
139 ieee->wdev.wiphy->max_scan_ie_len = 0;
140 ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
141 | BIT(NL80211_IFTYPE_ADHOC);
142 }
143
144 err = libipw_networks_allocate(ieee);
145 if (err) {
146 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
147 goto failed_free_wiphy;
148 }
149 libipw_networks_initialize(ieee);
150
151 /* Default fragmentation threshold is maximum payload size */
152 ieee->fts = DEFAULT_FTS;
153 ieee->rts = DEFAULT_FTS;
154 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
155 ieee->open_wep = 1;
156
157 /* Default to enabling full open WEP with host based encrypt/decrypt */
158 ieee->host_encrypt = 1;
159 ieee->host_decrypt = 1;
160 ieee->host_mc_decrypt = 1;
161
162 /* Host fragmentation in Open mode. Default is enabled.
163 * Note: host fragmentation is always enabled if host encryption
164 * is enabled. For cards can do hardware encryption, they must do
165 * hardware fragmentation as well. So we don't need a variable
166 * like host_enc_frag. */
167 ieee->host_open_frag = 1;
168 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
169
170 spin_lock_init(&ieee->lock);
171
172 libipw_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
173
174 ieee->wpa_enabled = 0;
175 ieee->drop_unencrypted = 0;
176 ieee->privacy_invoked = 0;
177
178 return dev;
179
180failed_free_wiphy:
181 if (!monitor)
182 wiphy_free(ieee->wdev.wiphy);
183failed_free_netdev:
184 free_netdev(dev);
185failed:
186 return NULL;
187}
188EXPORT_SYMBOL(alloc_libipw);
189
190void free_libipw(struct net_device *dev, int monitor)
191{
192 struct libipw_device *ieee = netdev_priv(dev);
193
194 libipw_crypt_info_free(&ieee->crypt_info);
195
196 libipw_networks_free(ieee);
197
198 /* free cfg80211 resources */
199 if (!monitor)
200 wiphy_free(ieee->wdev.wiphy);
201
202 free_netdev(dev);
203}
204EXPORT_SYMBOL(free_libipw);
205
206#ifdef CONFIG_LIBIPW_DEBUG
207
208static int debug = 0;
209u32 libipw_debug_level = 0;
210EXPORT_SYMBOL_GPL(libipw_debug_level);
211static struct proc_dir_entry *libipw_proc = NULL;
212
213static int debug_level_proc_show(struct seq_file *m, void *v)
214{
215 seq_printf(m, "0x%08X\n", libipw_debug_level);
216 return 0;
217}
218
219static int debug_level_proc_open(struct inode *inode, struct file *file)
220{
221 return single_open(file, debug_level_proc_show, NULL);
222}
223
224static ssize_t debug_level_proc_write(struct file *file,
225 const char __user *buffer, size_t count, loff_t *pos)
226{
227 char buf[] = "0x00000000\n";
228 size_t len = min(sizeof(buf) - 1, count);
229 unsigned long val;
230
231 if (copy_from_user(buf, buffer, len))
232 return count;
233 buf[len] = 0;
234 if (sscanf(buf, "%li", &val) != 1)
235 printk(KERN_INFO DRV_NAME
236 ": %s is not in hex or decimal form.\n", buf);
237 else
238 libipw_debug_level = val;
239
240 return strnlen(buf, len);
241}
242
243static const struct proc_ops debug_level_proc_ops = {
244 .proc_open = debug_level_proc_open,
245 .proc_read = seq_read,
246 .proc_lseek = seq_lseek,
247 .proc_release = single_release,
248 .proc_write = debug_level_proc_write,
249};
250#endif /* CONFIG_LIBIPW_DEBUG */
251
252static int __init libipw_init(void)
253{
254 int err;
255#ifdef CONFIG_LIBIPW_DEBUG
256 struct proc_dir_entry *e;
257
258 libipw_debug_level = debug;
259 libipw_proc = proc_mkdir(DRV_PROCNAME, init_net.proc_net);
260 if (libipw_proc == NULL) {
261 LIBIPW_ERROR("Unable to create " DRV_PROCNAME
262 " proc directory\n");
263 return -EIO;
264 }
265 e = proc_create("debug_level", 0644, libipw_proc,
266 &debug_level_proc_ops);
267 if (!e) {
268 remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
269 libipw_proc = NULL;
270 return -EIO;
271 }
272#endif /* CONFIG_LIBIPW_DEBUG */
273
274 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
275 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
276
277 err = libipw_crypto_init();
278 if (err)
279 goto remove_debugfs;
280 err = libipw_crypto_ccmp_init();
281 if (err)
282 goto uninit_crypto;
283 err = libipw_crypto_tkip_init();
284 if (err)
285 goto uninit_crypto_ccmp;
286 err = libipw_crypto_wep_init();
287 if (err)
288 goto uninit_crypto_tkip;
289
290 return 0;
291uninit_crypto_tkip:
292 libipw_crypto_tkip_exit();
293uninit_crypto_ccmp:
294 libipw_crypto_ccmp_exit();
295uninit_crypto:
296 libipw_crypto_exit();
297remove_debugfs:
298#ifdef CONFIG_LIBIPW_DEBUG
299 remove_proc_entry("debug_level", libipw_proc);
300 remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
301 libipw_proc = NULL;
302#endif
303 return err;
304}
305
306static void __exit libipw_exit(void)
307{
308#ifdef CONFIG_LIBIPW_DEBUG
309 if (libipw_proc) {
310 remove_proc_entry("debug_level", libipw_proc);
311 remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
312 libipw_proc = NULL;
313 }
314#endif /* CONFIG_LIBIPW_DEBUG */
315
316 libipw_crypto_ccmp_exit();
317 libipw_crypto_tkip_exit();
318 libipw_crypto_wep_exit();
319 libipw_crypto_exit();
320}
321
322#ifdef CONFIG_LIBIPW_DEBUG
323#include <linux/moduleparam.h>
324module_param(debug, int, 0444);
325MODULE_PARM_DESC(debug, "debug output mask");
326#endif /* CONFIG_LIBIPW_DEBUG */
327
328module_exit(libipw_exit);
329module_init(libipw_init);
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
87static 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
95void 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}
108EXPORT_SYMBOL(libipw_networks_age);
109
110static 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
121int 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}
128EXPORT_SYMBOL(libipw_change_mtu);
129
130struct 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
203failed_free_wiphy:
204 if (!monitor)
205 wiphy_free(ieee->wdev.wiphy);
206failed_free_netdev:
207 free_netdev(dev);
208failed:
209 return NULL;
210}
211EXPORT_SYMBOL(alloc_libipw);
212
213void 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}
227EXPORT_SYMBOL(free_libipw);
228
229#ifdef CONFIG_LIBIPW_DEBUG
230
231static int debug = 0;
232u32 libipw_debug_level = 0;
233EXPORT_SYMBOL_GPL(libipw_debug_level);
234static struct proc_dir_entry *libipw_proc = NULL;
235
236static 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
242static int debug_level_proc_open(struct inode *inode, struct file *file)
243{
244 return single_open(file, debug_level_proc_show, NULL);
245}
246
247static 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
266static 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
276static 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
303static 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>
316module_param(debug, int, 0444);
317MODULE_PARM_DESC(debug, "debug output mask");
318#endif /* CONFIG_LIBIPW_DEBUG */
319
320module_exit(libipw_exit);
321module_init(libipw_init);