]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - net/ieee80211/ieee80211_module.c
[PATCH] Unlinline a bunch of other functions
[mirror_ubuntu-bionic-kernel.git] / net / ieee80211 / ieee80211_module.c
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 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.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 James P. Ketrenos <ipw2100-admin@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/config.h>
35 #include <linux/errno.h>
36 #include <linux/if_arp.h>
37 #include <linux/in6.h>
38 #include <linux/in.h>
39 #include <linux/ip.h>
40 #include <linux/kernel.h>
41 #include <linux/module.h>
42 #include <linux/netdevice.h>
43 #include <linux/proc_fs.h>
44 #include <linux/skbuff.h>
45 #include <linux/slab.h>
46 #include <linux/tcp.h>
47 #include <linux/types.h>
48 #include <linux/wireless.h>
49 #include <linux/etherdevice.h>
50 #include <asm/uaccess.h>
51 #include <net/arp.h>
52
53 #include <net/ieee80211.h>
54
55 #define DRV_DESCRIPTION "802.11 data/management/control stack"
56 #define DRV_NAME "ieee80211"
57 #define DRV_VERSION IEEE80211_VERSION
58 #define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
59
60 MODULE_VERSION(DRV_VERSION);
61 MODULE_DESCRIPTION(DRV_DESCRIPTION);
62 MODULE_AUTHOR(DRV_COPYRIGHT);
63 MODULE_LICENSE("GPL");
64
65 static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
66 {
67 if (ieee->networks)
68 return 0;
69
70 ieee->networks =
71 kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
72 GFP_KERNEL);
73 if (!ieee->networks) {
74 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
75 ieee->dev->name);
76 return -ENOMEM;
77 }
78
79 memset(ieee->networks, 0,
80 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
81
82 return 0;
83 }
84
85 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
86 {
87 if (!ieee->networks)
88 return;
89 kfree(ieee->networks);
90 ieee->networks = NULL;
91 }
92
93 static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
94 {
95 int i;
96
97 INIT_LIST_HEAD(&ieee->network_free_list);
98 INIT_LIST_HEAD(&ieee->network_list);
99 for (i = 0; i < MAX_NETWORK_COUNT; i++)
100 list_add_tail(&ieee->networks[i].list,
101 &ieee->network_free_list);
102 }
103
104 struct net_device *alloc_ieee80211(int sizeof_priv)
105 {
106 struct ieee80211_device *ieee;
107 struct net_device *dev;
108 int err;
109
110 IEEE80211_DEBUG_INFO("Initializing...\n");
111
112 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
113 if (!dev) {
114 IEEE80211_ERROR("Unable to network device.\n");
115 goto failed;
116 }
117 ieee = netdev_priv(dev);
118 dev->hard_start_xmit = ieee80211_xmit;
119
120 ieee->dev = dev;
121
122 err = ieee80211_networks_allocate(ieee);
123 if (err) {
124 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
125 goto failed;
126 }
127 ieee80211_networks_initialize(ieee);
128
129 /* Default fragmentation threshold is maximum payload size */
130 ieee->fts = DEFAULT_FTS;
131 ieee->rts = DEFAULT_FTS;
132 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
133 ieee->open_wep = 1;
134
135 /* Default to enabling full open WEP with host based encrypt/decrypt */
136 ieee->host_encrypt = 1;
137 ieee->host_decrypt = 1;
138 ieee->host_mc_decrypt = 1;
139
140 /* Host fragementation in Open mode. Default is enabled.
141 * Note: host fragmentation is always enabled if host encryption
142 * is enabled. For cards can do hardware encryption, they must do
143 * hardware fragmentation as well. So we don't need a variable
144 * like host_enc_frag. */
145 ieee->host_open_frag = 1;
146 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
147
148 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
149 init_timer(&ieee->crypt_deinit_timer);
150 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
151 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
152 ieee->crypt_quiesced = 0;
153
154 spin_lock_init(&ieee->lock);
155
156 ieee->wpa_enabled = 0;
157 ieee->drop_unencrypted = 0;
158 ieee->privacy_invoked = 0;
159
160 return dev;
161
162 failed:
163 if (dev)
164 free_netdev(dev);
165 return NULL;
166 }
167
168 void free_ieee80211(struct net_device *dev)
169 {
170 struct ieee80211_device *ieee = netdev_priv(dev);
171
172 int i;
173
174 ieee80211_crypt_quiescing(ieee);
175 del_timer_sync(&ieee->crypt_deinit_timer);
176 ieee80211_crypt_deinit_entries(ieee, 1);
177
178 for (i = 0; i < WEP_KEYS; i++) {
179 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
180 if (crypt) {
181 if (crypt->ops) {
182 crypt->ops->deinit(crypt->priv);
183 module_put(crypt->ops->owner);
184 }
185 kfree(crypt);
186 ieee->crypt[i] = NULL;
187 }
188 }
189
190 ieee80211_networks_free(ieee);
191 free_netdev(dev);
192 }
193
194 #ifdef CONFIG_IEEE80211_DEBUG
195
196 static int debug = 0;
197 u32 ieee80211_debug_level = 0;
198 struct proc_dir_entry *ieee80211_proc = NULL;
199
200 static int show_debug_level(char *page, char **start, off_t offset,
201 int count, int *eof, void *data)
202 {
203 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
204 }
205
206 static int store_debug_level(struct file *file, const char __user * buffer,
207 unsigned long count, void *data)
208 {
209 char buf[] = "0x00000000\n";
210 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
211 unsigned long val;
212
213 if (copy_from_user(buf, buffer, len))
214 return count;
215 buf[len] = 0;
216 if (sscanf(buf, "%li", &val) != 1)
217 printk(KERN_INFO DRV_NAME
218 ": %s is not in hex or decimal form.\n", buf);
219 else
220 ieee80211_debug_level = val;
221
222 return strnlen(buf, len);
223 }
224 #endif /* CONFIG_IEEE80211_DEBUG */
225
226 static int __init ieee80211_init(void)
227 {
228 #ifdef CONFIG_IEEE80211_DEBUG
229 struct proc_dir_entry *e;
230
231 ieee80211_debug_level = debug;
232 ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
233 if (ieee80211_proc == NULL) {
234 IEEE80211_ERROR("Unable to create " DRV_NAME
235 " proc directory\n");
236 return -EIO;
237 }
238 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
239 ieee80211_proc);
240 if (!e) {
241 remove_proc_entry(DRV_NAME, proc_net);
242 ieee80211_proc = NULL;
243 return -EIO;
244 }
245 e->read_proc = show_debug_level;
246 e->write_proc = store_debug_level;
247 e->data = NULL;
248 #endif /* CONFIG_IEEE80211_DEBUG */
249
250 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
251 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
252
253 return 0;
254 }
255
256 static void __exit ieee80211_exit(void)
257 {
258 #ifdef CONFIG_IEEE80211_DEBUG
259 if (ieee80211_proc) {
260 remove_proc_entry("debug_level", ieee80211_proc);
261 remove_proc_entry(DRV_NAME, proc_net);
262 ieee80211_proc = NULL;
263 }
264 #endif /* CONFIG_IEEE80211_DEBUG */
265 }
266
267 #ifdef CONFIG_IEEE80211_DEBUG
268 #include <linux/moduleparam.h>
269 module_param(debug, int, 0444);
270 MODULE_PARM_DESC(debug, "debug output mask");
271 #endif /* CONFIG_IEEE80211_DEBUG */
272
273 module_exit(ieee80211_exit);
274 module_init(ieee80211_init);
275
276 const char *escape_essid(const char *essid, u8 essid_len)
277 {
278 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
279 const char *s = essid;
280 char *d = escaped;
281
282 if (ieee80211_is_empty_essid(essid, essid_len)) {
283 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
284 return escaped;
285 }
286
287 essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
288 while (essid_len--) {
289 if (*s == '\0') {
290 *d++ = '\\';
291 *d++ = '0';
292 s++;
293 } else {
294 *d++ = *s++;
295 }
296 }
297 *d = '\0';
298 return escaped;
299 }
300
301 EXPORT_SYMBOL(alloc_ieee80211);
302 EXPORT_SYMBOL(free_ieee80211);
303 EXPORT_SYMBOL(escape_essid);