From 7e272fcff6f0a32a3d46e600ea5895f6058f4e2d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 24 Sep 2008 18:13:14 -0400 Subject: wireless: consolidate on a single escape_essid implementation Signed-off-by: John W. Linville --- net/wireless/lib80211.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 net/wireless/lib80211.c (limited to 'net/wireless/lib80211.c') diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c new file mode 100644 index 000000000000..b22d271fb675 --- /dev/null +++ b/net/wireless/lib80211.c @@ -0,0 +1,58 @@ +/* + * lib80211 -- common bits for IEEE802.11 drivers + * + * Copyright(c) 2008 John W. Linville + * + */ + +#include +#include + +#include + +#define DRV_NAME "lib80211" + +#define DRV_DESCRIPTION "common routines for IEEE802.11 drivers" + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR("John W. Linville "); +MODULE_LICENSE("GPL"); + +const char *escape_ssid(const char *ssid, u8 ssid_len) +{ + static char escaped[IEEE80211_MAX_SSID_LEN * 2 + 1]; + const char *s = ssid; + char *d = escaped; + + if (is_empty_ssid(ssid, ssid_len)) { + memcpy(escaped, "", sizeof("")); + return escaped; + } + + ssid_len = min_t(u8, ssid_len, IEEE80211_MAX_SSID_LEN); + while (ssid_len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} +EXPORT_SYMBOL(escape_ssid); + +static int __init ieee80211_init(void) +{ + printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n"); + return 0; +} + +static void __exit ieee80211_exit(void) +{ +} + +module_init(ieee80211_init); +module_exit(ieee80211_exit); -- cgit v1.2.3 From c5d3dce875ef055ed9b14f169cc967cc2c8faf1f Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 30 Sep 2008 17:17:26 -0400 Subject: wireless: remove NETWORK_EMPTY_ESSID flag It is unnecessary and of questionable value. Also remove is_empty_ssid, as it is also unnecessary. Signed-off-by: John W. Linville --- net/wireless/lib80211.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'net/wireless/lib80211.c') diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c index b22d271fb675..872cc8dc00a3 100644 --- a/net/wireless/lib80211.c +++ b/net/wireless/lib80211.c @@ -24,11 +24,6 @@ const char *escape_ssid(const char *ssid, u8 ssid_len) const char *s = ssid; char *d = escaped; - if (is_empty_ssid(ssid, ssid_len)) { - memcpy(escaped, "", sizeof("")); - return escaped; - } - ssid_len = min_t(u8, ssid_len, IEEE80211_MAX_SSID_LEN); while (ssid_len--) { if (*s == '\0') { -- cgit v1.2.3 From 2819f8ad6da1e24b5dd94a221978e61f2a9c972a Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 30 Sep 2008 17:50:31 -0400 Subject: wireless: escape_ssid should handle non-printables Also use common backslash sequences like \t, \n, \r, and \\ as well as \0. Signed-off-by: John W. Linville --- net/wireless/lib80211.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'net/wireless/lib80211.c') diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c index 872cc8dc00a3..b8e34d31e757 100644 --- a/net/wireless/lib80211.c +++ b/net/wireless/lib80211.c @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -20,19 +21,31 @@ MODULE_LICENSE("GPL"); const char *escape_ssid(const char *ssid, u8 ssid_len) { - static char escaped[IEEE80211_MAX_SSID_LEN * 2 + 1]; + static char escaped[IEEE80211_MAX_SSID_LEN * 4 + 1]; const char *s = ssid; char *d = escaped; ssid_len = min_t(u8, ssid_len, IEEE80211_MAX_SSID_LEN); while (ssid_len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else { + if (isprint(*s)) { *d++ = *s++; + continue; } + + *d++ = '\\'; + if (*s == '\0') + *d++ = '0'; + else if (*s == '\n') + *d++ = 'n'; + else if (*s == '\r') + *d++ = 'r'; + else if (*s == '\t') + *d++ = 't'; + else if (*s == '\\') + *d++ = '\\'; + else + d += snprintf(d, 3, "%03o", *s); + s++; } *d = '\0'; return escaped; -- cgit v1.2.3 From 9387b7caf3049168fc97a8a9111af8fe2143af18 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 30 Sep 2008 20:59:05 -0400 Subject: wireless: use individual buffers for printing ssid values Also change escape_ssid to print_ssid to match print_mac semantics. Signed-off-by: John W. Linville --- net/wireless/lib80211.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'net/wireless/lib80211.c') diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c index b8e34d31e757..e71f7d085621 100644 --- a/net/wireless/lib80211.c +++ b/net/wireless/lib80211.c @@ -19,11 +19,10 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR("John W. Linville "); MODULE_LICENSE("GPL"); -const char *escape_ssid(const char *ssid, u8 ssid_len) +const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) { - static char escaped[IEEE80211_MAX_SSID_LEN * 4 + 1]; const char *s = ssid; - char *d = escaped; + char *d = buf; ssid_len = min_t(u8, ssid_len, IEEE80211_MAX_SSID_LEN); while (ssid_len--) { @@ -48,9 +47,9 @@ const char *escape_ssid(const char *ssid, u8 ssid_len) s++; } *d = '\0'; - return escaped; + return buf; } -EXPORT_SYMBOL(escape_ssid); +EXPORT_SYMBOL(print_ssid); static int __init ieee80211_init(void) { -- cgit v1.2.3 From 274bfb8dc5ffa16cb073801bebe76ab7f4e2e73d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 29 Oct 2008 11:35:05 -0400 Subject: 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 --- net/wireless/lib80211.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 186 insertions(+), 5 deletions(-) (limited to 'net/wireless/lib80211.c') 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 @@ * * Copyright(c) 2008 John W. Linville * + * Portions copied from old ieee80211 component, w/ original copyright + * notices below: + * + * Host AP crypto routines + * + * Copyright (c) 2002-2003, Jouni Malinen + * Portions Copyright (C) 2004, Intel Corporation + * */ #include #include #include +#include +#include +#include +#include #include @@ -19,6 +31,14 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR("John W. Linville "); MODULE_LICENSE("GPL"); +struct lib80211_crypto_alg { + struct list_head list; + struct lib80211_crypto_ops *ops; +}; + +static LIST_HEAD(lib80211_crypto_algs); +static DEFINE_SPINLOCK(lib80211_crypto_lock); + const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) { const char *s = ssid; @@ -51,15 +71,176 @@ const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) } EXPORT_SYMBOL(print_ssid); -static int __init ieee80211_init(void) +void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, int force) { - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n"); + struct lib80211_crypt_data *entry, *next; + unsigned long flags; + + spin_lock_irqsave(info->lock, flags); + list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) { + if (atomic_read(&entry->refcnt) != 0 && !force) + continue; + + list_del(&entry->list); + + if (entry->ops) { + entry->ops->deinit(entry->priv); + module_put(entry->ops->owner); + } + kfree(entry); + } + spin_unlock_irqrestore(info->lock, flags); +} +EXPORT_SYMBOL(lib80211_crypt_deinit_entries); + +/* After this, crypt_deinit_list won't accept new members */ +void lib80211_crypt_quiescing(struct lib80211_crypt_info *info) +{ + unsigned long flags; + + spin_lock_irqsave(info->lock, flags); + info->crypt_quiesced = 1; + spin_unlock_irqrestore(info->lock, flags); +} +EXPORT_SYMBOL(lib80211_crypt_quiescing); + +void lib80211_crypt_deinit_handler(unsigned long data) +{ + struct lib80211_crypt_info *info = (struct lib80211_crypt_info *)data; + unsigned long flags; + + lib80211_crypt_deinit_entries(info, 0); + + spin_lock_irqsave(info->lock, flags); + if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) { + printk(KERN_DEBUG "%s: entries remaining in delayed crypt " + "deletion list\n", info->name); + info->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&info->crypt_deinit_timer); + } + spin_unlock_irqrestore(info->lock, flags); +} +EXPORT_SYMBOL(lib80211_crypt_deinit_handler); + +void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info, + struct lib80211_crypt_data **crypt) +{ + struct lib80211_crypt_data *tmp; + unsigned long flags; + + if (*crypt == NULL) + return; + + tmp = *crypt; + *crypt = NULL; + + /* must not run ops->deinit() while there may be pending encrypt or + * decrypt operations. Use a list of delayed deinits to avoid needing + * locking. */ + + spin_lock_irqsave(info->lock, flags); + if (!info->crypt_quiesced) { + list_add(&tmp->list, &info->crypt_deinit_list); + if (!timer_pending(&info->crypt_deinit_timer)) { + info->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&info->crypt_deinit_timer); + } + } + spin_unlock_irqrestore(info->lock, flags); +} +EXPORT_SYMBOL(lib80211_crypt_delayed_deinit); + +int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops) +{ + unsigned long flags; + struct lib80211_crypto_alg *alg; + + alg = kzalloc(sizeof(*alg), GFP_KERNEL); + if (alg == NULL) + return -ENOMEM; + + alg->ops = ops; + + spin_lock_irqsave(&lib80211_crypto_lock, flags); + list_add(&alg->list, &lib80211_crypto_algs); + spin_unlock_irqrestore(&lib80211_crypto_lock, flags); + + printk(KERN_DEBUG "lib80211_crypt: registered algorithm '%s'\n", + ops->name); + + return 0; +} +EXPORT_SYMBOL(lib80211_register_crypto_ops); + +int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops) +{ + struct lib80211_crypto_alg *alg; + unsigned long flags; + + spin_lock_irqsave(&lib80211_crypto_lock, flags); + list_for_each_entry(alg, &lib80211_crypto_algs, list) { + if (alg->ops == ops) + goto found; + } + spin_unlock_irqrestore(&lib80211_crypto_lock, flags); + return -EINVAL; + + found: + printk(KERN_DEBUG "lib80211_crypt: unregistered algorithm " + "'%s'\n", ops->name); + list_del(&alg->list); + spin_unlock_irqrestore(&lib80211_crypto_lock, flags); + kfree(alg); return 0; } +EXPORT_SYMBOL(lib80211_unregister_crypto_ops); + +struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name) +{ + struct lib80211_crypto_alg *alg; + unsigned long flags; + + spin_lock_irqsave(&lib80211_crypto_lock, flags); + list_for_each_entry(alg, &lib80211_crypto_algs, list) { + if (strcmp(alg->ops->name, name) == 0) + goto found; + } + spin_unlock_irqrestore(&lib80211_crypto_lock, flags); + return NULL; + + found: + spin_unlock_irqrestore(&lib80211_crypto_lock, flags); + return alg->ops; +} +EXPORT_SYMBOL(lib80211_get_crypto_ops); + +static void *lib80211_crypt_null_init(int keyidx) +{ + return (void *)1; +} + +static void lib80211_crypt_null_deinit(void *priv) +{ +} + +static struct lib80211_crypto_ops lib80211_crypt_null = { + .name = "NULL", + .init = lib80211_crypt_null_init, + .deinit = lib80211_crypt_null_deinit, + .owner = THIS_MODULE, +}; + +static int __init lib80211_init(void) +{ + printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION "\n"); + return lib80211_register_crypto_ops(&lib80211_crypt_null); +} -static void __exit ieee80211_exit(void) +static void __exit lib80211_exit(void) { + lib80211_unregister_crypto_ops(&lib80211_crypt_null); + BUG_ON(!list_empty(&lib80211_crypto_algs)); } -module_init(ieee80211_init); -module_exit(ieee80211_exit); +module_init(lib80211_init); +module_exit(lib80211_exit); -- cgit v1.2.3 From 2ba4b32ecf748d5f45f298fc9677fa46d1dd9aff Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 11 Nov 2008 16:00:06 -0500 Subject: lib80211: consolidate crypt init routines Signed-off-by: John W. Linville --- net/wireless/lib80211.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'net/wireless/lib80211.c') diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c index d681721f4acb..97d411f74507 100644 --- a/net/wireless/lib80211.c +++ b/net/wireless/lib80211.c @@ -71,6 +71,44 @@ const char *print_ssid(char *buf, const char *ssid, u8 ssid_len) } EXPORT_SYMBOL(print_ssid); +int lib80211_crypt_info_init(struct lib80211_crypt_info *info, char *name, + spinlock_t *lock) +{ + memset(info, 0, sizeof(*info)); + + info->name = name; + info->lock = lock; + + INIT_LIST_HEAD(&info->crypt_deinit_list); + setup_timer(&info->crypt_deinit_timer, lib80211_crypt_deinit_handler, + (unsigned long)info); + + return 0; +} +EXPORT_SYMBOL(lib80211_crypt_info_init); + +void lib80211_crypt_info_free(struct lib80211_crypt_info *info) +{ + int i; + + lib80211_crypt_quiescing(info); + del_timer_sync(&info->crypt_deinit_timer); + lib80211_crypt_deinit_entries(info, 1); + + for (i = 0; i < NUM_WEP_KEYS; i++) { + struct lib80211_crypt_data *crypt = info->crypt[i]; + if (crypt) { + if (crypt->ops) { + crypt->ops->deinit(crypt->priv); + module_put(crypt->ops->owner); + } + kfree(crypt); + info->crypt[i] = NULL; + } + } +} +EXPORT_SYMBOL(lib80211_crypt_info_free); + void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, int force) { struct lib80211_crypt_data *entry, *next; -- cgit v1.2.3