const struct ieee80211_authenticator_backend * ieee80211_authenticator_backend_get(const char *name) { if (backend == NULL) ieee80211_load_module("wlan_radius"); return backend && strcmp(backend->iab_name, name) == 0 ? backend : NULL; }
const struct ieee80211_aclator * ieee80211_aclator_get(const char *name) { if (acl == NULL) ieee80211_load_module("wlan_acl"); return acl && strcmp(acl->iac_name, name) == 0 ? acl : NULL; }
struct ath_ratectrl *ieee80211_rate_attach(struct ath_softc *sc, const char *name) { int id; char buf[64]; struct ath_ratectrl *ctl; snprintf(buf, sizeof(buf), "ath_rate_%s", name); for (id = 0; id < IEEE80211_RATE_MAX; id++) { if (strcmp(buf, module_names[id]) == 0) break; } if (id >= IEEE80211_RATE_MAX) { printk(KERN_ERR "Module \"%s\" is not known\n", buf); return NULL; } if (!ratectls[id].attach) ieee80211_load_module(buf); if (!ratectls[id].attach) { printk(KERN_ERR "Error loading module \"%s\"\n", buf); return NULL; } ctl = ratectls[id].attach(sc); if (!ctl) { printk(KERN_ERR "Module \"%s\" failed to initialize\n", buf); return NULL; } ctl->ops = &ratectls[id]; return ctl; }
const struct ieee80211_authenticator * ieee80211_authenticator_get(int auth) { if (auth >= IEEE80211_AUTH_MAX) return NULL; if (authenticators[auth] == NULL) ieee80211_load_module(auth_modnames[auth]); return authenticators[auth]; }
const struct ieee80211_scanner * ieee80211_scanner_get(enum ieee80211_opmode mode) { if (mode >= IEEE80211_OPMODE_MAX) return NULL; if (scanners[mode] == NULL) ieee80211_load_module(scan_modnames[mode]); return scanners[mode]; }
const struct ieee80211_authenticator * ieee80211_authenticator_get(int auth) { static int initialized = 0; if (!initialized) { ieee80211_auth_setup(); initialized = 1; } if (auth >= IEEE80211_AUTH_MAX) return NULL; if (authenticators[auth] == NULL) ieee80211_load_module(auth_modnames[auth]); return authenticators[auth]; }
void ieee80211_ratectl_set(struct ieee80211vap *vap, int type) { if (type >= IEEE80211_RATECTL_MAX) return; if (ratectls[type] == NULL) { ieee80211_load_module(ratectl_modnames[type]); if (ratectls[type] == NULL) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL, "%s: unable to load algo %u, module %s\n", __func__, type, ratectl_modnames[type]); vap->iv_rate = ratectls[IEEE80211_RATECTL_NONE]; return; } } vap->iv_rate = ratectls[type]; }
/* * Establish a relationship between the specified key and cipher * and, if necessary, allocate a hardware index from the driver. * Note that when a fixed key index is required it must be specified. * * This must be the first call applied to a key; all the other key * routines assume wk_cipher is setup. * * Locking must be handled by the caller using: * ieee80211_key_update_begin(vap); * ieee80211_key_update_end(vap); */ int ieee80211_crypto_newkey(struct ieee80211vap *vap, int cipher, int flags, struct ieee80211_key *key) { struct ieee80211com *ic = vap->iv_ic; const struct ieee80211_cipher *cip; ieee80211_keyix keyix, rxkeyix; void *keyctx; int oflags; IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: cipher %u flags 0x%x keyix %u\n", __func__, cipher, flags, key->wk_keyix); /* * Validate cipher and set reference to cipher routines. */ if (cipher >= IEEE80211_CIPHER_MAX) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: invalid cipher %u\n", __func__, cipher); vap->iv_stats.is_crypto_badcipher++; 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>. */ 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_modnames[cipher]); vap->iv_stats.is_crypto_nocipher++; return 0; } } oflags = key->wk_flags; flags &= IEEE80211_KEY_COMMON; /* NB: preserve device attributes */ flags |= (oflags & IEEE80211_KEY_DEVICE); /* * If the hardware does not support the cipher then * fallback to a host-based implementation. */ if ((ic->ic_cryptocaps & (1<<cipher)) == 0) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: no h/w support for cipher %s, falling back to s/w\n", __func__, cip->ic_name); flags |= IEEE80211_KEY_SWCRYPT; } /* * Hardware TKIP with software MIC is an important * combination; we handle it by flagging each key, * the cipher modules honor it. */ if (cipher == IEEE80211_CIPHER_TKIP && (ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIPMIC) == 0) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: no h/w support for TKIP MIC, falling back to s/w\n", __func__); flags |= IEEE80211_KEY_SWMIC; } /* * Bind cipher to key instance. Note we do this * after checking the device capabilities so the * cipher module can optimize space usage based on * whether or not it needs to do the cipher work. */ if (key->wk_cipher != cip || key->wk_flags != flags) { /* * Fillin the flags so cipher modules can see s/w * crypto requirements and potentially allocate * different state and/or attach different method * pointers. */ key->wk_flags = flags; keyctx = cip->ic_attach(vap, key); if (keyctx == NULL) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: unable to attach cipher %s\n", __func__, cip->ic_name); key->wk_flags = oflags; /* restore old flags */ vap->iv_stats.is_crypto_attachfail++; return 0; } cipher_detach(key); key->wk_cipher = cip; /* XXX refcnt? */ key->wk_private = keyctx; } /* * Ask the driver for a key index if we don't have one. * Note that entries in the global key table always have * an index; this means it's safe to call this routine * for these entries just to setup the reference to the * cipher template. Note also that when using software * crypto we also call the driver to give us a key index. */ if ((key->wk_flags & IEEE80211_KEY_DEVKEY) == 0) { if (!dev_key_alloc(vap, key, &keyix, &rxkeyix)) { /* * Unable to setup driver state. */ vap->iv_stats.is_crypto_keyfail++; IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: unable to setup cipher %s\n", __func__, cip->ic_name); return 0; } if (key->wk_flags != flags) { /* * Driver overrode flags we setup; typically because * resources were unavailable to handle _this_ key. * Re-attach the cipher context to allow cipher * modules to handle differing requirements. */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: driver override for cipher %s, flags " "0x%x -> 0x%x\n", __func__, cip->ic_name, oflags, key->wk_flags); keyctx = cip->ic_attach(vap, key); if (keyctx == NULL) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: unable to attach cipher %s with " "flags 0x%x\n", __func__, cip->ic_name, key->wk_flags); key->wk_flags = oflags; /* restore old flags */ vap->iv_stats.is_crypto_attachfail++; return 0; } cipher_detach(key); key->wk_cipher = cip; /* XXX refcnt? */ key->wk_private = keyctx; } key->wk_keyix = keyix; key->wk_rxkeyix = rxkeyix; key->wk_flags |= IEEE80211_KEY_DEVKEY; } return 1; }
/* * Establish a relationship between the specified key and cipher * and, if necessary, allocate a hardware index from the driver. * Note that when a fixed key index is required it must be specified * and we blindly assign it w/o consulting the driver (XXX). * * This must be the first call applied to a key; all the other key * routines assume wk_cipher is setup. * * Locking must be handled by the caller using: * ieee80211_key_update_begin(ic); * ieee80211_key_update_end(ic); */ int ieee80211_crypto_newkey(struct ieee80211com *ic, int cipher, int flags, struct ieee80211_key *key) { #define N(a) (sizeof(a) / sizeof(a[0])) const struct ieee80211_cipher *cip; ieee80211_keyix keyix, rxkeyix; void *keyctx; int oflags; /* * Validate cipher and set reference to cipher routines. */ if (cipher >= IEEE80211_CIPHER_MAX) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "%s: invalid cipher %u\n", __func__, cipher); ic->ic_stats.is_crypto_badcipher++; 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(ic, 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(ic, IEEE80211_MSG_CRYPTO, "%s: unable to load cipher %u, module %s\n", __func__, cipher, cipher < N(cipher_modnames) ? cipher_modnames[cipher] : "<unknown>"); ic->ic_stats.is_crypto_nocipher++; return 0; } } oflags = key->wk_flags; flags &= IEEE80211_KEY_COMMON; /* * If the hardware does not support the cipher then * fallback to a host-based implementation. */ if ((ic->ic_caps & (1<<cipher)) == 0) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "%s: no h/w support for cipher %s, falling back to s/w\n", __func__, cip->ic_name); flags |= IEEE80211_KEY_SWCRYPT; } /* * Hardware TKIP with software MIC is an important * combination; we handle it by flagging each key, * the cipher modules honor it. */ if (cipher == IEEE80211_CIPHER_TKIP && (ic->ic_caps & IEEE80211_C_TKIPMIC) == 0) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "%s: no h/w support for TKIP MIC, falling back to s/w\n", __func__); flags |= IEEE80211_KEY_SWMIC; } /* * Bind cipher to key instance. Note we do this * after checking the device capabilities so the * cipher module can optimize space usage based on * whether or not it needs to do the cipher work. */ if (key->wk_cipher != cip || key->wk_flags != flags) { again: /* * Fillin the flags so cipher modules can see s/w * crypto requirements and potentially allocate * different state and/or attach different method * pointers. * * XXX this is not right when s/w crypto fallback * fails and we try to restore previous state. */ key->wk_flags = flags; keyctx = cip->ic_attach(ic, key); if (keyctx == NULL) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "%s: unable to attach cipher %s\n", __func__, cip->ic_name); key->wk_flags = oflags; /* restore old flags */ ic->ic_stats.is_crypto_attachfail++; return 0; } cipher_detach(key); key->wk_cipher = cip; /* XXX refcnt? */ key->wk_private = keyctx; } /* * Commit to requested usage so driver can see the flags. */ key->wk_flags = flags; /* * Ask the driver for a key index if we don't have one. * Note that entries in the global key table always have * an index; this means it's safe to call this routine * for these entries just to setup the reference to the * cipher template. Note also that when using software * crypto we also call the driver to give us a key index. */ if (key->wk_keyix == IEEE80211_KEYIX_NONE) { if (!dev_key_alloc(ic, key, &keyix, &rxkeyix)) { /* * Driver has no room; fallback to doing crypto * in the host. We change the flags and start the * procedure over. If we get back here then there's * no hope and we bail. Note that this can leave * the key in a inconsistent state if the caller * continues to use it. */ if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { ic->ic_stats.is_crypto_swfallback++; IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "%s: no h/w resources for cipher %s, " "falling back to s/w\n", __func__, cip->ic_name); oflags = key->wk_flags; flags |= IEEE80211_KEY_SWCRYPT; if (cipher == IEEE80211_CIPHER_TKIP) flags |= IEEE80211_KEY_SWMIC; goto again; } ic->ic_stats.is_crypto_keyfail++; IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "%s: unable to setup cipher %s\n", __func__, cip->ic_name); return 0; } key->wk_keyix = keyix; key->wk_rxkeyix = rxkeyix; } return 1; #undef N }