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