diff options
Diffstat (limited to 'net/ieee80211')
-rw-r--r-- | net/ieee80211/ieee80211_crypt.c | 152 |
1 files changed, 41 insertions, 111 deletions
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c index 20cc580a07e0..ecc9bb196abc 100644 --- a/net/ieee80211/ieee80211_crypt.c +++ b/net/ieee80211/ieee80211_crypt.c | |||
@@ -11,15 +11,14 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/config.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <asm/string.h> | 18 | #include <linux/string.h> |
19 | #include <asm/errno.h> | ||
20 | |||
21 | #include <net/ieee80211.h> | 19 | #include <net/ieee80211.h> |
22 | 20 | ||
21 | |||
23 | MODULE_AUTHOR("Jouni Malinen"); | 22 | MODULE_AUTHOR("Jouni Malinen"); |
24 | MODULE_DESCRIPTION("HostAP crypto"); | 23 | MODULE_DESCRIPTION("HostAP crypto"); |
25 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
@@ -29,32 +28,20 @@ struct ieee80211_crypto_alg { | |||
29 | struct ieee80211_crypto_ops *ops; | 28 | struct ieee80211_crypto_ops *ops; |
30 | }; | 29 | }; |
31 | 30 | ||
32 | struct ieee80211_crypto { | 31 | static LIST_HEAD(ieee80211_crypto_algs); |
33 | struct list_head algs; | 32 | static DEFINE_SPINLOCK(ieee80211_crypto_lock); |
34 | spinlock_t lock; | ||
35 | }; | ||
36 | |||
37 | static struct ieee80211_crypto *hcrypt; | ||
38 | 33 | ||
39 | void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) | 34 | void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) |
40 | { | 35 | { |
41 | struct list_head *ptr, *n; | 36 | struct ieee80211_crypt_data *entry, *next; |
42 | struct ieee80211_crypt_data *entry; | ||
43 | unsigned long flags; | 37 | unsigned long flags; |
44 | 38 | ||
45 | spin_lock_irqsave(&ieee->lock, flags); | 39 | spin_lock_irqsave(&ieee->lock, flags); |
46 | 40 | list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) { | |
47 | if (list_empty(&ieee->crypt_deinit_list)) | ||
48 | goto unlock; | ||
49 | |||
50 | for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; | ||
51 | ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { | ||
52 | entry = list_entry(ptr, struct ieee80211_crypt_data, list); | ||
53 | |||
54 | if (atomic_read(&entry->refcnt) != 0 && !force) | 41 | if (atomic_read(&entry->refcnt) != 0 && !force) |
55 | continue; | 42 | continue; |
56 | 43 | ||
57 | list_del(ptr); | 44 | list_del(&entry->list); |
58 | 45 | ||
59 | if (entry->ops) { | 46 | if (entry->ops) { |
60 | entry->ops->deinit(entry->priv); | 47 | entry->ops->deinit(entry->priv); |
@@ -62,7 +49,6 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) | |||
62 | } | 49 | } |
63 | kfree(entry); | 50 | kfree(entry); |
64 | } | 51 | } |
65 | unlock: | ||
66 | spin_unlock_irqrestore(&ieee->lock, flags); | 52 | spin_unlock_irqrestore(&ieee->lock, flags); |
67 | } | 53 | } |
68 | 54 | ||
@@ -125,9 +111,6 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) | |||
125 | unsigned long flags; | 111 | unsigned long flags; |
126 | struct ieee80211_crypto_alg *alg; | 112 | struct ieee80211_crypto_alg *alg; |
127 | 113 | ||
128 | if (hcrypt == NULL) | ||
129 | return -1; | ||
130 | |||
131 | alg = kmalloc(sizeof(*alg), GFP_KERNEL); | 114 | alg = kmalloc(sizeof(*alg), GFP_KERNEL); |
132 | if (alg == NULL) | 115 | if (alg == NULL) |
133 | return -ENOMEM; | 116 | return -ENOMEM; |
@@ -135,9 +118,9 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) | |||
135 | memset(alg, 0, sizeof(*alg)); | 118 | memset(alg, 0, sizeof(*alg)); |
136 | alg->ops = ops; | 119 | alg->ops = ops; |
137 | 120 | ||
138 | spin_lock_irqsave(&hcrypt->lock, flags); | 121 | spin_lock_irqsave(&ieee80211_crypto_lock, flags); |
139 | list_add(&alg->list, &hcrypt->algs); | 122 | list_add(&alg->list, &ieee80211_crypto_algs); |
140 | spin_unlock_irqrestore(&hcrypt->lock, flags); | 123 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); |
141 | 124 | ||
142 | printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n", | 125 | printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n", |
143 | ops->name); | 126 | ops->name); |
@@ -147,64 +130,49 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) | |||
147 | 130 | ||
148 | int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) | 131 | int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) |
149 | { | 132 | { |
133 | struct ieee80211_crypto_alg *alg; | ||
150 | unsigned long flags; | 134 | unsigned long flags; |
151 | struct list_head *ptr; | ||
152 | struct ieee80211_crypto_alg *del_alg = NULL; | ||
153 | |||
154 | if (hcrypt == NULL) | ||
155 | return -1; | ||
156 | |||
157 | spin_lock_irqsave(&hcrypt->lock, flags); | ||
158 | for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { | ||
159 | struct ieee80211_crypto_alg *alg = | ||
160 | (struct ieee80211_crypto_alg *)ptr; | ||
161 | if (alg->ops == ops) { | ||
162 | list_del(&alg->list); | ||
163 | del_alg = alg; | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | spin_unlock_irqrestore(&hcrypt->lock, flags); | ||
168 | 135 | ||
169 | if (del_alg) { | 136 | spin_lock_irqsave(&ieee80211_crypto_lock, flags); |
170 | printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " | 137 | list_for_each_entry(alg, &ieee80211_crypto_algs, list) { |
171 | "'%s'\n", ops->name); | 138 | if (alg->ops == ops) |
172 | kfree(del_alg); | 139 | goto found; |
173 | } | 140 | } |
174 | 141 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); | |
175 | return del_alg ? 0 : -1; | 142 | return -EINVAL; |
143 | |||
144 | found: | ||
145 | printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " | ||
146 | "'%s'\n", ops->name); | ||
147 | list_del(&alg->list); | ||
148 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); | ||
149 | kfree(alg); | ||
150 | return 0; | ||
176 | } | 151 | } |
177 | 152 | ||
178 | struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) | 153 | struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) |
179 | { | 154 | { |
155 | struct ieee80211_crypto_alg *alg; | ||
180 | unsigned long flags; | 156 | unsigned long flags; |
181 | struct list_head *ptr; | 157 | |
182 | struct ieee80211_crypto_alg *found_alg = NULL; | 158 | spin_lock_irqsave(&ieee80211_crypto_lock, flags); |
183 | 159 | list_for_each_entry(alg, &ieee80211_crypto_algs, list) { | |
184 | if (hcrypt == NULL) | 160 | if (strcmp(alg->ops->name, name) == 0) |
185 | return NULL; | 161 | goto found; |
186 | |||
187 | spin_lock_irqsave(&hcrypt->lock, flags); | ||
188 | for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { | ||
189 | struct ieee80211_crypto_alg *alg = | ||
190 | (struct ieee80211_crypto_alg *)ptr; | ||
191 | if (strcmp(alg->ops->name, name) == 0) { | ||
192 | found_alg = alg; | ||
193 | break; | ||
194 | } | ||
195 | } | 162 | } |
196 | spin_unlock_irqrestore(&hcrypt->lock, flags); | 163 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); |
164 | return NULL; | ||
197 | 165 | ||
198 | if (found_alg) | 166 | found: |
199 | return found_alg->ops; | 167 | spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); |
200 | else | 168 | return alg->ops; |
201 | return NULL; | ||
202 | } | 169 | } |
203 | 170 | ||
204 | static void *ieee80211_crypt_null_init(int keyidx) | 171 | static void *ieee80211_crypt_null_init(int keyidx) |
205 | { | 172 | { |
206 | return (void *)1; | 173 | return (void *)1; |
207 | } | 174 | } |
175 | |||
208 | static void ieee80211_crypt_null_deinit(void *priv) | 176 | static void ieee80211_crypt_null_deinit(void *priv) |
209 | { | 177 | { |
210 | } | 178 | } |
@@ -213,56 +181,18 @@ static struct ieee80211_crypto_ops ieee80211_crypt_null = { | |||
213 | .name = "NULL", | 181 | .name = "NULL", |
214 | .init = ieee80211_crypt_null_init, | 182 | .init = ieee80211_crypt_null_init, |
215 | .deinit = ieee80211_crypt_null_deinit, | 183 | .deinit = ieee80211_crypt_null_deinit, |
216 | .encrypt_mpdu = NULL, | ||
217 | .decrypt_mpdu = NULL, | ||
218 | .encrypt_msdu = NULL, | ||
219 | .decrypt_msdu = NULL, | ||
220 | .set_key = NULL, | ||
221 | .get_key = NULL, | ||
222 | .extra_mpdu_prefix_len = 0, | ||
223 | .extra_mpdu_postfix_len = 0, | ||
224 | .owner = THIS_MODULE, | 184 | .owner = THIS_MODULE, |
225 | }; | 185 | }; |
226 | 186 | ||
227 | static int __init ieee80211_crypto_init(void) | 187 | static int __init ieee80211_crypto_init(void) |
228 | { | 188 | { |
229 | int ret = -ENOMEM; | 189 | return ieee80211_register_crypto_ops(&ieee80211_crypt_null); |
230 | |||
231 | hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL); | ||
232 | if (!hcrypt) | ||
233 | goto out; | ||
234 | |||
235 | memset(hcrypt, 0, sizeof(*hcrypt)); | ||
236 | INIT_LIST_HEAD(&hcrypt->algs); | ||
237 | spin_lock_init(&hcrypt->lock); | ||
238 | |||
239 | ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null); | ||
240 | if (ret < 0) { | ||
241 | kfree(hcrypt); | ||
242 | hcrypt = NULL; | ||
243 | } | ||
244 | out: | ||
245 | return ret; | ||
246 | } | 190 | } |
247 | 191 | ||
248 | static void __exit ieee80211_crypto_deinit(void) | 192 | static void __exit ieee80211_crypto_deinit(void) |
249 | { | 193 | { |
250 | struct list_head *ptr, *n; | 194 | ieee80211_unregister_crypto_ops(&ieee80211_crypt_null); |
251 | 195 | BUG_ON(!list_empty(&ieee80211_crypto_algs)); | |
252 | if (hcrypt == NULL) | ||
253 | return; | ||
254 | |||
255 | for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; | ||
256 | ptr = n, n = ptr->next) { | ||
257 | struct ieee80211_crypto_alg *alg = | ||
258 | (struct ieee80211_crypto_alg *)ptr; | ||
259 | list_del(ptr); | ||
260 | printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " | ||
261 | "'%s' (deinit)\n", alg->ops->name); | ||
262 | kfree(alg); | ||
263 | } | ||
264 | |||
265 | kfree(hcrypt); | ||
266 | } | 196 | } |
267 | 197 | ||
268 | EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); | 198 | EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); |