1 /* 2 * lib80211 -- common bits for IEEE802.11 drivers 3 * 4 * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com> 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 * 14 */ 15 16 #include <linux/module.h> 17 #include <linux/ctype.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> 23 24 #include <net/lib80211.h> 25 26 #define DRV_NAME "lib80211" 27 28 #define DRV_DESCRIPTION "common routines for IEEE802.11 drivers" 29 30 MODULE_DESCRIPTION(DRV_DESCRIPTION); 31 MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>"); 32 MODULE_LICENSE("GPL"); 33 34 struct lib80211_crypto_alg { 35 struct list_head list; 36 struct lib80211_crypto_ops *ops; 37 }; 38 39 static LIST_HEAD(lib80211_crypto_algs); 40 static DEFINE_SPINLOCK(lib80211_crypto_lock); 41 42 const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) 43 { 44 const char *s = ssid; 45 char *d = buf; 46 47 ssid_len = min_t(u8, ssid_len, IEEE80211_MAX_SSID_LEN); 48 while (ssid_len--) { 49 if (isprint(*s)) { 50 *d++ = *s++; 51 continue; 52 } 53 54 *d++ = '\\'; 55 if (*s == '\0') 56 *d++ = '0'; 57 else if (*s == '\n') 58 *d++ = 'n'; 59 else if (*s == '\r') 60 *d++ = 'r'; 61 else if (*s == '\t') 62 *d++ = 't'; 63 else if (*s == '\\') 64 *d++ = '\\'; 65 else 66 d += snprintf(d, 3, "%03o", *s); 67 s++; 68 } 69 *d = '\0'; 70 return buf; 71 } 72 EXPORT_SYMBOL(print_ssid); 73 74 int lib80211_crypt_info_init(struct lib80211_crypt_info *info, char *name, 75 spinlock_t *lock) 76 { 77 memset(info, 0, sizeof(*info)); 78 79 info->name = name; 80 info->lock = lock; 81 82 INIT_LIST_HEAD(&info->crypt_deinit_list); 83 setup_timer(&info->crypt_deinit_timer, lib80211_crypt_deinit_handler, 84 (unsigned long)info); 85 86 return 0; 87 } 88 EXPORT_SYMBOL(lib80211_crypt_info_init); 89 90 void lib80211_crypt_info_free(struct lib80211_crypt_info *info) 91 { 92 int i; 93 94 lib80211_crypt_quiescing(info); 95 del_timer_sync(&info->crypt_deinit_timer); 96 lib80211_crypt_deinit_entries(info, 1); 97 98 for (i = 0; i < NUM_WEP_KEYS; i++) { 99 struct lib80211_crypt_data *crypt = info->crypt[i]; 100 if (crypt) { 101 if (crypt->ops) { 102 crypt->ops->deinit(crypt->priv); 103 module_put(crypt->ops->owner); 104 } 105 kfree(crypt); 106 info->crypt[i] = NULL; 107 } 108 } 109 } 110 EXPORT_SYMBOL(lib80211_crypt_info_free); 111 112 void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, int force) 113 { 114 struct lib80211_crypt_data *entry, *next; 115 unsigned long flags; 116 117 spin_lock_irqsave(info->lock, flags); 118 list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) { 119 if (atomic_read(&entry->refcnt) != 0 && !force) 120 continue; 121 122 list_del(&entry->list); 123 124 if (entry->ops) { 125 entry->ops->deinit(entry->priv); 126 module_put(entry->ops->owner); 127 } 128 kfree(entry); 129 } 130 spin_unlock_irqrestore(info->lock, flags); 131 } 132 EXPORT_SYMBOL(lib80211_crypt_deinit_entries); 133 134 /* After this, crypt_deinit_list won't accept new members */ 135 void lib80211_crypt_quiescing(struct lib80211_crypt_info *info) 136 { 137 unsigned long flags; 138 139 spin_lock_irqsave(info->lock, flags); 140 info->crypt_quiesced = 1; 141 spin_unlock_irqrestore(info->lock, flags); 142 } 143 EXPORT_SYMBOL(lib80211_crypt_quiescing); 144 145 void lib80211_crypt_deinit_handler(unsigned long data) 146 { 147 struct lib80211_crypt_info *info = (struct lib80211_crypt_info *)data; 148 unsigned long flags; 149 150 lib80211_crypt_deinit_entries(info, 0); 151 152 spin_lock_irqsave(info->lock, flags); 153 if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) { 154 printk(KERN_DEBUG "%s: entries remaining in delayed crypt " 155 "deletion list\n", info->name); 156 info->crypt_deinit_timer.expires = jiffies + HZ; 157 add_timer(&info->crypt_deinit_timer); 158 } 159 spin_unlock_irqrestore(info->lock, flags); 160 } 161 EXPORT_SYMBOL(lib80211_crypt_deinit_handler); 162 163 void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info, 164 struct lib80211_crypt_data **crypt) 165 { 166 struct lib80211_crypt_data *tmp; 167 unsigned long flags; 168 169 if (*crypt == NULL) 170 return; 171 172 tmp = *crypt; 173 *crypt = NULL; 174 175 /* must not run ops->deinit() while there may be pending encrypt or 176 * decrypt operations. Use a list of delayed deinits to avoid needing 177 * locking. */ 178 179 spin_lock_irqsave(info->lock, flags); 180 if (!info->crypt_quiesced) { 181 list_add(&tmp->list, &info->crypt_deinit_list); 182 if (!timer_pending(&info->crypt_deinit_timer)) { 183 info->crypt_deinit_timer.expires = jiffies + HZ; 184 add_timer(&info->crypt_deinit_timer); 185 } 186 } 187 spin_unlock_irqrestore(info->lock, flags); 188 } 189 EXPORT_SYMBOL(lib80211_crypt_delayed_deinit); 190 191 int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops) 192 { 193 unsigned long flags; 194 struct lib80211_crypto_alg *alg; 195 196 alg = kzalloc(sizeof(*alg), GFP_KERNEL); 197 if (alg == NULL) 198 return -ENOMEM; 199 200 alg->ops = ops; 201 202 spin_lock_irqsave(&lib80211_crypto_lock, flags); 203 list_add(&alg->list, &lib80211_crypto_algs); 204 spin_unlock_irqrestore(&lib80211_crypto_lock, flags); 205 206 printk(KERN_DEBUG "lib80211_crypt: registered algorithm '%s'\n", 207 ops->name); 208 209 return 0; 210 } 211 EXPORT_SYMBOL(lib80211_register_crypto_ops); 212 213 int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops) 214 { 215 struct lib80211_crypto_alg *alg; 216 unsigned long flags; 217 218 spin_lock_irqsave(&lib80211_crypto_lock, flags); 219 list_for_each_entry(alg, &lib80211_crypto_algs, list) { 220 if (alg->ops == ops) 221 goto found; 222 } 223 spin_unlock_irqrestore(&lib80211_crypto_lock, flags); 224 return -EINVAL; 225 226 found: 227 printk(KERN_DEBUG "lib80211_crypt: unregistered algorithm " 228 "'%s'\n", ops->name); 229 list_del(&alg->list); 230 spin_unlock_irqrestore(&lib80211_crypto_lock, flags); 231 kfree(alg); 232 return 0; 233 } 234 EXPORT_SYMBOL(lib80211_unregister_crypto_ops); 235 236 struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name) 237 { 238 struct lib80211_crypto_alg *alg; 239 unsigned long flags; 240 241 spin_lock_irqsave(&lib80211_crypto_lock, flags); 242 list_for_each_entry(alg, &lib80211_crypto_algs, list) { 243 if (strcmp(alg->ops->name, name) == 0) 244 goto found; 245 } 246 spin_unlock_irqrestore(&lib80211_crypto_lock, flags); 247 return NULL; 248 249 found: 250 spin_unlock_irqrestore(&lib80211_crypto_lock, flags); 251 return alg->ops; 252 } 253 EXPORT_SYMBOL(lib80211_get_crypto_ops); 254 255 static void *lib80211_crypt_null_init(int keyidx) 256 { 257 return (void *)1; 258 } 259 260 static void lib80211_crypt_null_deinit(void *priv) 261 { 262 } 263 264 static struct lib80211_crypto_ops lib80211_crypt_null = { 265 .name = "NULL", 266 .init = lib80211_crypt_null_init, 267 .deinit = lib80211_crypt_null_deinit, 268 .owner = THIS_MODULE, 269 }; 270 271 static int __init lib80211_init(void) 272 { 273 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n"); 274 return lib80211_register_crypto_ops(&lib80211_crypt_null); 275 } 276 277 static void __exit lib80211_exit(void) 278 { 279 lib80211_unregister_crypto_ops(&lib80211_crypt_null); 280 BUG_ON(!list_empty(&lib80211_crypto_algs)); 281 } 282 283 module_init(lib80211_init); 284 module_exit(lib80211_exit); 285