Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * lib80211 -- common bits for IEEE802.11 drivers
0004  *
0005  * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com>
0006  *
0007  * Portions copied from old ieee80211 component, w/ original copyright
0008  * notices below:
0009  *
0010  * Host AP crypto routines
0011  *
0012  * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
0013  * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
0014  *
0015  */
0016 
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018 
0019 #include <linux/module.h>
0020 #include <linux/ctype.h>
0021 #include <linux/ieee80211.h>
0022 #include <linux/errno.h>
0023 #include <linux/init.h>
0024 #include <linux/slab.h>
0025 #include <linux/string.h>
0026 
0027 #include <net/lib80211.h>
0028 
0029 #define DRV_DESCRIPTION "common routines for IEEE802.11 drivers"
0030 
0031 MODULE_DESCRIPTION(DRV_DESCRIPTION);
0032 MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>");
0033 MODULE_LICENSE("GPL");
0034 
0035 struct lib80211_crypto_alg {
0036     struct list_head list;
0037     struct lib80211_crypto_ops *ops;
0038 };
0039 
0040 static LIST_HEAD(lib80211_crypto_algs);
0041 static DEFINE_SPINLOCK(lib80211_crypto_lock);
0042 
0043 static void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info,
0044                       int force);
0045 static void lib80211_crypt_quiescing(struct lib80211_crypt_info *info);
0046 static void lib80211_crypt_deinit_handler(struct timer_list *t);
0047 
0048 int lib80211_crypt_info_init(struct lib80211_crypt_info *info, char *name,
0049                 spinlock_t *lock)
0050 {
0051     memset(info, 0, sizeof(*info));
0052 
0053     info->name = name;
0054     info->lock = lock;
0055 
0056     INIT_LIST_HEAD(&info->crypt_deinit_list);
0057     timer_setup(&info->crypt_deinit_timer, lib80211_crypt_deinit_handler,
0058             0);
0059 
0060     return 0;
0061 }
0062 EXPORT_SYMBOL(lib80211_crypt_info_init);
0063 
0064 void lib80211_crypt_info_free(struct lib80211_crypt_info *info)
0065 {
0066     int i;
0067 
0068         lib80211_crypt_quiescing(info);
0069         del_timer_sync(&info->crypt_deinit_timer);
0070         lib80211_crypt_deinit_entries(info, 1);
0071 
0072         for (i = 0; i < NUM_WEP_KEYS; i++) {
0073                 struct lib80211_crypt_data *crypt = info->crypt[i];
0074                 if (crypt) {
0075                         if (crypt->ops) {
0076                                 crypt->ops->deinit(crypt->priv);
0077                                 module_put(crypt->ops->owner);
0078                         }
0079                         kfree(crypt);
0080                         info->crypt[i] = NULL;
0081                 }
0082         }
0083 }
0084 EXPORT_SYMBOL(lib80211_crypt_info_free);
0085 
0086 static void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info,
0087                       int force)
0088 {
0089     struct lib80211_crypt_data *entry, *next;
0090     unsigned long flags;
0091 
0092     spin_lock_irqsave(info->lock, flags);
0093     list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) {
0094         if (atomic_read(&entry->refcnt) != 0 && !force)
0095             continue;
0096 
0097         list_del(&entry->list);
0098 
0099         if (entry->ops) {
0100             entry->ops->deinit(entry->priv);
0101             module_put(entry->ops->owner);
0102         }
0103         kfree(entry);
0104     }
0105     spin_unlock_irqrestore(info->lock, flags);
0106 }
0107 
0108 /* After this, crypt_deinit_list won't accept new members */
0109 static void lib80211_crypt_quiescing(struct lib80211_crypt_info *info)
0110 {
0111     unsigned long flags;
0112 
0113     spin_lock_irqsave(info->lock, flags);
0114     info->crypt_quiesced = 1;
0115     spin_unlock_irqrestore(info->lock, flags);
0116 }
0117 
0118 static void lib80211_crypt_deinit_handler(struct timer_list *t)
0119 {
0120     struct lib80211_crypt_info *info = from_timer(info, t,
0121                               crypt_deinit_timer);
0122     unsigned long flags;
0123 
0124     lib80211_crypt_deinit_entries(info, 0);
0125 
0126     spin_lock_irqsave(info->lock, flags);
0127     if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) {
0128         printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
0129                "deletion list\n", info->name);
0130         info->crypt_deinit_timer.expires = jiffies + HZ;
0131         add_timer(&info->crypt_deinit_timer);
0132     }
0133     spin_unlock_irqrestore(info->lock, flags);
0134 }
0135 
0136 void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info,
0137                     struct lib80211_crypt_data **crypt)
0138 {
0139     struct lib80211_crypt_data *tmp;
0140     unsigned long flags;
0141 
0142     if (*crypt == NULL)
0143         return;
0144 
0145     tmp = *crypt;
0146     *crypt = NULL;
0147 
0148     /* must not run ops->deinit() while there may be pending encrypt or
0149      * decrypt operations. Use a list of delayed deinits to avoid needing
0150      * locking. */
0151 
0152     spin_lock_irqsave(info->lock, flags);
0153     if (!info->crypt_quiesced) {
0154         list_add(&tmp->list, &info->crypt_deinit_list);
0155         if (!timer_pending(&info->crypt_deinit_timer)) {
0156             info->crypt_deinit_timer.expires = jiffies + HZ;
0157             add_timer(&info->crypt_deinit_timer);
0158         }
0159     }
0160     spin_unlock_irqrestore(info->lock, flags);
0161 }
0162 EXPORT_SYMBOL(lib80211_crypt_delayed_deinit);
0163 
0164 int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops)
0165 {
0166     unsigned long flags;
0167     struct lib80211_crypto_alg *alg;
0168 
0169     alg = kzalloc(sizeof(*alg), GFP_KERNEL);
0170     if (alg == NULL)
0171         return -ENOMEM;
0172 
0173     alg->ops = ops;
0174 
0175     spin_lock_irqsave(&lib80211_crypto_lock, flags);
0176     list_add(&alg->list, &lib80211_crypto_algs);
0177     spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
0178 
0179     printk(KERN_DEBUG "lib80211_crypt: registered algorithm '%s'\n",
0180            ops->name);
0181 
0182     return 0;
0183 }
0184 EXPORT_SYMBOL(lib80211_register_crypto_ops);
0185 
0186 int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops)
0187 {
0188     struct lib80211_crypto_alg *alg;
0189     unsigned long flags;
0190 
0191     spin_lock_irqsave(&lib80211_crypto_lock, flags);
0192     list_for_each_entry(alg, &lib80211_crypto_algs, list) {
0193         if (alg->ops == ops)
0194             goto found;
0195     }
0196     spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
0197     return -EINVAL;
0198 
0199       found:
0200     printk(KERN_DEBUG "lib80211_crypt: unregistered algorithm '%s'\n",
0201            ops->name);
0202     list_del(&alg->list);
0203     spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
0204     kfree(alg);
0205     return 0;
0206 }
0207 EXPORT_SYMBOL(lib80211_unregister_crypto_ops);
0208 
0209 struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name)
0210 {
0211     struct lib80211_crypto_alg *alg;
0212     unsigned long flags;
0213 
0214     spin_lock_irqsave(&lib80211_crypto_lock, flags);
0215     list_for_each_entry(alg, &lib80211_crypto_algs, list) {
0216         if (strcmp(alg->ops->name, name) == 0)
0217             goto found;
0218     }
0219     spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
0220     return NULL;
0221 
0222       found:
0223     spin_unlock_irqrestore(&lib80211_crypto_lock, flags);
0224     return alg->ops;
0225 }
0226 EXPORT_SYMBOL(lib80211_get_crypto_ops);
0227 
0228 static void *lib80211_crypt_null_init(int keyidx)
0229 {
0230     return (void *)1;
0231 }
0232 
0233 static void lib80211_crypt_null_deinit(void *priv)
0234 {
0235 }
0236 
0237 static struct lib80211_crypto_ops lib80211_crypt_null = {
0238     .name = "NULL",
0239     .init = lib80211_crypt_null_init,
0240     .deinit = lib80211_crypt_null_deinit,
0241     .owner = THIS_MODULE,
0242 };
0243 
0244 static int __init lib80211_init(void)
0245 {
0246     pr_info(DRV_DESCRIPTION "\n");
0247     return lib80211_register_crypto_ops(&lib80211_crypt_null);
0248 }
0249 
0250 static void __exit lib80211_exit(void)
0251 {
0252     lib80211_unregister_crypto_ops(&lib80211_crypt_null);
0253     BUG_ON(!list_empty(&lib80211_crypto_algs));
0254 }
0255 
0256 module_init(lib80211_init);
0257 module_exit(lib80211_exit);