Project : madwifi
Revision : 2260
Author : mentor (Matthew W. S. Bell)
Date : 2007-04-09 21:15:41 +0200 (Mon, 09 Apr 2007)
Log Message :
Do not call request_module from any context other than process. This was
being done by the net80211 crypto functions.
Affected Files:
* trunk/net80211/ieee80211_crypto.c updated
* trunk/net80211/ieee80211_crypto.h updated
* trunk/net80211/ieee80211_crypto_ccmp.c updated
* trunk/net80211/ieee80211_linux.c updated
* trunk/net80211/ieee80211_scan.c updated
* trunk/net80211/ieee80211_wireless.c updated
Modified: trunk/net80211/ieee80211_crypto.c
===================================================================
--- trunk/net80211/ieee80211_crypto.c 2007-04-09 17:53:57 UTC (rev 2259)
+++ trunk/net80211/ieee80211_crypto.c 2007-04-09 19:15:41 UTC (rev 2260)
@@ -239,22 +239,59 @@
}
EXPORT_SYMBOL(ieee80211_crypto_unregister);
-int
-ieee80211_crypto_available(u_int cipher)
-{
- return cipher < IEEE80211_CIPHER_MAX && ciphers[cipher] != NULL;
-}
-EXPORT_SYMBOL(ieee80211_crypto_available);
-
/* XXX well-known names! */
static const char *cipher_modnames[] = {
- "wlan_wep", /* IEEE80211_CIPHER_WEP */
- "wlan_tkip", /* IEEE80211_CIPHER_TKIP */
+ "wlan_wep", /* IEEE80211_CIPHER_WEP */
+ "wlan_tkip", /* IEEE80211_CIPHER_TKIP */
"wlan_aes_ocb", /* IEEE80211_CIPHER_AES_OCB */
"wlan_ccmp", /* IEEE80211_CIPHER_AES_CCM */
- "wlan_ckip", /* IEEE80211_CIPHER_CKIP */
+ "wlan_ckip", /* IEEE80211_CIPHER_CKIP */
};
+
+int
+ieee80211_crypto_available(struct ieee80211vap *vap, u_int cipher)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ unsigned int status = 0;
+
+ if (cipher < IEEE80211_CIPHER_MAX) {
+ if (ciphers[cipher] == NULL) {
+ /*
+ * Auto-load cipher module if we have a well-known name
+ * for it. It might be better to use string names
rather
+ * than numbers and craft a module name based on the
cipher
+ * name; e.g. wlan_cipher_<cipher-name>.
+ */
+ if (cipher < N(cipher_modnames)) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
+ "%s: unregistered cipher %u,
load module %s\n",
+ __func__, cipher,
cipher_modnames[cipher]);
+ ieee80211_load_module(cipher_modnames[cipher]);
+
+ /*
+ * If cipher module loaded it should immediately
+ * call ieee80211_crypto_register which will
fill
+ * in the entry in the ciphers array.
+ */
+ if (ciphers[cipher] == NULL) {
+ IEEE80211_DPRINTF(vap,
IEEE80211_MSG_CRYPTO,
+ "%s: unable to load
cipher %u, module %s\n",
+ __func__, cipher,
+ cipher <
N(cipher_modnames) ?
+ cipher_modnames[cipher]
: "<unknown>");
+ vap->iv_stats.is_crypto_nocipher++;
+ } else
+ status = 1;
+ }
+ } else
+ status = 1;
+ }
+ return status;
+#undef N
+}
+EXPORT_SYMBOL(ieee80211_crypto_available);
+
/*
* Establish a relationship between the specified key and cipher
* and, if necessary, allocate a hardware index from the driver.
@@ -272,7 +309,6 @@
ieee80211_crypto_newkey(struct ieee80211vap *vap,
int cipher, int flags, struct ieee80211_key *key)
{
-#define N(a) (sizeof(a) / sizeof(a[0]))
const struct ieee80211_cipher *cip;
void *keyctx;
int oflags;
@@ -287,35 +323,8 @@
return 0;
}
cip = ciphers[cipher];
- if (cip == NULL) {
- /*
- * Auto-load cipher module if we have a well-known name
- * for it. It might be better to use string names rather
- * than numbers and craft a module name based on the cipher
- * name; e.g. wlan_cipher_<cipher-name>.
- */
- if (cipher < N(cipher_modnames)) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
- "%s: unregistered cipher %u, load module %s\n",
- __func__, cipher, cipher_modnames[cipher]);
- ieee80211_load_module(cipher_modnames[cipher]);
- /*
- * If cipher module loaded it should immediately
- * call ieee80211_crypto_register which will fill
- * in the entry in the ciphers array.
- */
- cip = ciphers[cipher];
- }
- if (cip == NULL) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
- "%s: unable to load cipher %u, module %s\n",
- __func__, cipher,
- cipher < N(cipher_modnames) ?
- cipher_modnames[cipher] : "<unknown>");
- vap->iv_stats.is_crypto_nocipher++;
- return 0;
- }
- }
+ if (cip == NULL)
+ return 0;
oflags = key->wk_flags;
flags &= IEEE80211_KEY_COMMON;
@@ -425,7 +434,6 @@
}
}
return 1;
-#undef N
}
EXPORT_SYMBOL(ieee80211_crypto_newkey);
Modified: trunk/net80211/ieee80211_crypto.h
===================================================================
--- trunk/net80211/ieee80211_crypto.h 2007-04-09 17:53:57 UTC (rev 2259)
+++ trunk/net80211/ieee80211_crypto.h 2007-04-09 19:15:41 UTC (rev 2260)
@@ -149,7 +149,7 @@
void ieee80211_crypto_register(const struct ieee80211_cipher *);
void ieee80211_crypto_unregister(const struct ieee80211_cipher *);
-int ieee80211_crypto_available(u_int);
+int ieee80211_crypto_available(struct ieee80211vap*, u_int);
struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
struct sk_buff *);
Modified: trunk/net80211/ieee80211_crypto_ccmp.c
===================================================================
--- trunk/net80211/ieee80211_crypto_ccmp.c 2007-04-09 17:53:57 UTC (rev
2259)
+++ trunk/net80211/ieee80211_crypto_ccmp.c 2007-04-09 19:15:41 UTC (rev
2260)
@@ -57,6 +57,11 @@
#define AES_BLOCK_LEN 16
+/* This function might sleep; this means it can only be called in contexts
+ * where we may sleep. This means that it cannot be used from soft-IRQs or
+ * hard-IRQs.
+ * Context: process
+ */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
#define crypto_cipher crypto_tfm
#define crypto_alloc_cipher(name,type,mask) crypto_alloc_tfm(name,type)
@@ -113,6 +118,13 @@
ctx->cc_vap = vap;
ctx->cc_ic = vap->iv_ic;
+ ctx->cc_tfm = crypto_alloc_tfm("aes", 0);
+ if (ctx->cc_tfm == NULL) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
+ "%s: unable to load kernel AES crypto
support\n",
+ __func__);
+ }
+
return ctx;
}
@@ -141,10 +153,6 @@
}
if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
- if (ctx->cc_tfm == NULL)
- ctx->cc_tfm = crypto_alloc_cipher("aes", 0,
- CRYPTO_ALG_ASYNC);
-
if (ctx->cc_tfm == NULL) {
IEEE80211_DPRINTF(ctx->cc_vap, IEEE80211_MSG_CRYPTO,
"%s: Tried to add a software crypto key, but
software crypto not available\n",
@@ -154,6 +162,7 @@
crypto_cipher_setkey(ctx->cc_tfm, k->wk_key, k->wk_keylen);
}
+
return 1;
}
Modified: trunk/net80211/ieee80211_linux.c
===================================================================
--- trunk/net80211/ieee80211_linux.c 2007-04-09 17:53:57 UTC (rev 2259)
+++ trunk/net80211/ieee80211_linux.c 2007-04-09 19:15:41 UTC (rev 2260)
@@ -317,7 +317,11 @@
}
EXPORT_SYMBOL(ieee80211_notify_michael_failure);
-/*
+/* This function might sleep; this means it can only be called in contexts
+ * where we may sleep. This means that it cannot be used from soft-IRQs or
+ * hard-IRQs.
+ * Context: process
+ *
* Note that a successful call to this function does not guarantee that
* the services provided by the requested module are available:
*
Modified: trunk/net80211/ieee80211_scan.c
===================================================================
--- trunk/net80211/ieee80211_scan.c 2007-04-09 17:53:57 UTC (rev 2259)
+++ trunk/net80211/ieee80211_scan.c 2007-04-09 19:15:41 UTC (rev 2260)
@@ -182,6 +182,12 @@
};
static const struct ieee80211_scanner *scanners[IEEE80211_SCANNER_MAX];
+/* If try load is set, this function will attempt to automatically load the
+ * requested module if it is not present. This is on operation that may sleep,
+ * as such, may only be called from contexts where we may sleep. Those are not
+ * hard-IRQs or soft-IRQs.
+ * if !!tryload, then Context: process
+ */
const struct ieee80211_scanner *
ieee80211_scanner_get(enum ieee80211_opmode mode, int tryload)
{
Modified: trunk/net80211/ieee80211_wireless.c
===================================================================
--- trunk/net80211/ieee80211_wireless.c 2007-04-09 17:53:57 UTC (rev 2259)
+++ trunk/net80211/ieee80211_wireless.c 2007-04-09 19:15:41 UTC (rev 2260)
@@ -2128,7 +2128,7 @@
break;
case IEEE80211_PARAM_MCASTCIPHER:
if ((vap->iv_caps & cipher2cap(value)) == 0 &&
- !ieee80211_crypto_available(value))
+ !ieee80211_crypto_available(vap, value))
return -EINVAL;
rsn->rsn_mcastcipher = value;
if (vap->iv_flags & IEEE80211_F_WPA)
@@ -2153,7 +2153,7 @@
for (j = 1; j < 32; j++) /* NB: skip WEP */
if ((value & (1 << j)) &&
((vap->iv_caps & cipher2cap(j)) ||
- ieee80211_crypto_available(j)))
+ ieee80211_crypto_available(vap, j)))
caps |= 1 << j;
if (caps == 0) /* nothing available */
return -EINVAL;
@@ -2165,7 +2165,7 @@
break;
case IEEE80211_PARAM_UCASTCIPHER:
if ((vap->iv_caps & cipher2cap(value)) == 0 &&
- !ieee80211_crypto_available(value))
+ !ieee80211_crypto_available(vap, value))
return -EINVAL;
rsn->rsn_ucastcipher = value;
if (vap->iv_flags & IEEE80211_F_WPA)
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
|