aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/lib80211.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2008-10-29 11:35:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-21 11:08:17 -0500
commit274bfb8dc5ffa16cb073801bebe76ab7f4e2e73d (patch)
tree04cd3f6a062496911b56737daa6a0858b769ccd6 /net/wireless/lib80211.c
parentdfe1bafdbac1c7b48b636fb7ace799e78170e0d6 (diff)
lib80211: absorb crypto bits from net/ieee80211
These bits are shared already between ipw2x00 and hostap, and could probably be shared both more cleanly and with other drivers. This commit simply relocates the code to lib80211 and adjusts the drivers appropriately. Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/lib80211.c')
-rw-r--r--net/wireless/lib80211.c191
1 files changed, 186 insertions, 5 deletions
diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c
index e71f7d085621..d681721f4acb 100644
--- a/net/wireless/lib80211.c
+++ b/net/wireless/lib80211.c
@@ -3,11 +3,23 @@
3 * 3 *
4 * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com> 4 * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com>
5 * 5 *
6 * Portions copied from old ieee80211 component, w/ original copyright
7 * notices below:
8 *
9 * Host AP crypto routines
10 *
11 * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
12 * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
13 *
6 */ 14 */
7 15
8#include <linux/module.h> 16#include <linux/module.h>
9#include <linux/ctype.h> 17#include <linux/ctype.h>
10#include <linux/ieee80211.h> 18#include <linux/ieee80211.h>
19#include <linux/errno.h>
20#include <linux/init.h>
21#include <linux/slab.h>
22#include <linux/string.h>
11 23
12#include <net/lib80211.h> 24#include <net/lib80211.h>
13 25
@@ -19,6 +31,14 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
19MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>"); 31MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>");
20MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
21 33
34struct lib80211_crypto_alg {
35 struct list_head list;
36 struct lib80211_crypto_ops *ops;
37};
38
39static LIST_HEAD(lib80211_crypto_algs);
40static DEFINE_SPINLOCK(lib80211_crypto_lock);
41
22const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) 42const char *print_ssid(char *buf, const char *ssid, u8 ssid_len)
23{ 43{
24 const char *s = ssid; 44 const char *s = ssid;
@@ -51,15 +71,176 @@ const char *print_ssid(char *buf, const char *ssid, u8 ssid_len)
51} 71}
52EXPORT_SYMBOL(print_ssid); 72EXPORT_SYMBOL(print_ssid);
53 73
54static int __init ieee80211_init(void) 74void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, int force)
55{ 75{
56 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n"); 76 struct lib80211_crypt_data *entry, *next;
77 unsigned long flags;
78
79 spin_lock_irqsave(info->lock, flags);
80 list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) {
81 if (atomic_read(&entry->refcnt) != 0 && !force)
82 continue;
83
84 list_del(&entry->list);
85
86 if (entry->ops) {
87 entry->ops->deinit(entry->priv);
88 module_put(entry->ops->owner);
89 }
90 kfree(entry);
91 }
92 spin_unlock_irqrestore(info->lock, flags);
93}
94EXPORT_SYMBOL(lib80211_crypt_deinit_entries);
95
96/* After this, crypt_deinit_list won't accept new members */
97void lib80211_crypt_quiescing(struct lib80211_crypt_info *info)
98{
99 unsigned long flags;
100
101 spin_lock_irqsave(info->lock, flags);
102 info->crypt_quiesced = 1;
103 spin_unlock_irqrestore(info->lock, flags);
104}
105EXPORT_SYMBOL(lib80211_crypt_quiescing);
106
107void lib80211_crypt_deinit_handler(unsigned long data)
108{
109 struct lib80211_crypt_info *info = (struct lib80211_crypt_info *)data;
110 unsigned long flags;
111
112 lib80211_crypt_deinit_entries(info, 0);
113
114 spin_lock_irqsave(info->lock, flags);
115 if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) {
116 printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
117 "deletion list\n", info->name);
118 info->crypt_deinit_timer.expires = jiffies + HZ;
119 add_timer(&info->crypt_deinit_timer);
120 }
121 spin_unlock_irqrestore(info->lock, flags);
122}
123EXPORT_SYMBOL(lib80211_crypt_deinit_handler);
124
125void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info,
126 struct lib80211_crypt_data **crypt)
127{
128 struct lib80211_crypt_data *tmp;
129 unsigned long flags;
130
131 if (*crypt == NULL)
132 return;
133
134 tmp = *crypt;
135 *crypt = NULL;
136
137 /* must not run ops->deinit() while there may be pending encrypt or
138 * decrypt operations. Use a list of delayed deinits to avoid needing
139 * locking. */
140
141 spin_lock_irqsave(info->lock, flags);
142 if (!info->crypt_quiesced) {
143 list_add(&tmp->list, &info->crypt_deinit_list);
144 if (!timer_pending(&info->crypt_deinit_timer)) {
145 info->crypt_deinit_timer.expires = jiffies + HZ;
146 add_timer(&info->crypt_deinit_timer);
147 }
148 }
149 spin_unlock_irqrestore(info->lock, flags);
150}
151EXPORT_SYMBOL(lib80211_crypt_delayed_deinit);
152
153int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops)
154{
155 unsigned long flags;
156 struct lib80211_crypto_alg *alg;
157
158 alg = kzalloc(sizeof(*alg), GFP_KERNEL);
159 if (alg == NULL)
160 return -ENOMEM;
161
162 alg->ops = ops;
163
164 spin_lock_irqsave(&lib80211_crypto_lock, flags);
165 list_add(&alg->list, &lib80211_crypto_algs);
166 spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
167
168 printk(KERN_DEBUG "lib80211_crypt: registered algorithm '%s'\n",
169 ops->name);
170
171 return 0;
172}
173EXPORT_SYMBOL(lib80211_register_crypto_ops);
174
175int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops)
176{
177 struct lib80211_crypto_alg *alg;
178 unsigned long flags;
179
180 spin_lock_irqsave(&lib80211_crypto_lock, flags);
181 list_for_each_entry(alg, &lib80211_crypto_algs, list) {
182 if (alg->ops == ops)
183 goto found;
184 }
185 spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
186 return -EINVAL;
187
188 found:
189 printk(KERN_DEBUG "lib80211_crypt: unregistered algorithm "
190 "'%s'\n", ops->name);
191 list_del(&alg->list);
192 spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
193 kfree(alg);
57 return 0; 194 return 0;
58} 195}
196EXPORT_SYMBOL(lib80211_unregister_crypto_ops);
197
198struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name)
199{
200 struct lib80211_crypto_alg *alg;
201 unsigned long flags;
202
203 spin_lock_irqsave(&lib80211_crypto_lock, flags);
204 list_for_each_entry(alg, &lib80211_crypto_algs, list) {
205 if (strcmp(alg->ops->name, name) == 0)
206 goto found;
207 }
208 spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
209 return NULL;
210
211 found:
212 spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
213 return alg->ops;
214}
215EXPORT_SYMBOL(lib80211_get_crypto_ops);
216
217static void *lib80211_crypt_null_init(int keyidx)
218{
219 return (void *)1;
220}
221
222static void lib80211_crypt_null_deinit(void *priv)
223{
224}
225
226static struct lib80211_crypto_ops lib80211_crypt_null = {
227 .name = "NULL",
228 .init = lib80211_crypt_null_init,
229 .deinit = lib80211_crypt_null_deinit,
230 .owner = THIS_MODULE,
231};
232
233static int __init lib80211_init(void)
234{
235 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n");
236 return lib80211_register_crypto_ops(&lib80211_crypt_null);
237}
59 238
60static void __exit ieee80211_exit(void) 239static void __exit lib80211_exit(void)
61{ 240{
241 lib80211_unregister_crypto_ops(&lib80211_crypt_null);
242 BUG_ON(!list_empty(&lib80211_crypto_algs));
62} 243}
63 244
64module_init(ieee80211_init); 245module_init(lib80211_init);
65module_exit(ieee80211_exit); 246module_exit(lib80211_exit);