diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 107 |
1 files changed, 68 insertions, 39 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d9ce33663c73..5e09d354c5a5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -658,7 +658,6 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) bool have_wep = !(IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)); bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE; - const struct ieee80211_cipher_scheme *cs = local->hw.cipher_schemes; int n_suites = 0, r = 0, w = 0; u32 *suites; static const u32 cipher_suites[] = { @@ -667,79 +666,109 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, + WLAN_CIPHER_SUITE_CCMP_256, + WLAN_CIPHER_SUITE_GCMP, + WLAN_CIPHER_SUITE_GCMP_256, /* keep last -- depends on hw flags! */ - WLAN_CIPHER_SUITE_AES_CMAC + WLAN_CIPHER_SUITE_AES_CMAC, + WLAN_CIPHER_SUITE_BIP_CMAC_256, + WLAN_CIPHER_SUITE_BIP_GMAC_128, + WLAN_CIPHER_SUITE_BIP_GMAC_256, }; - /* Driver specifies the ciphers, we have nothing to do... */ - if (local->hw.wiphy->cipher_suites && have_wep) - return 0; + if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL || + local->hw.wiphy->cipher_suites) { + /* If the driver advertises, or doesn't support SW crypto, + * we only need to remove WEP if necessary. + */ + if (have_wep) + return 0; + + /* well if it has _no_ ciphers ... fine */ + if (!local->hw.wiphy->n_cipher_suites) + return 0; + + /* Driver provides cipher suites, but we need to exclude WEP */ + suites = kmemdup(local->hw.wiphy->cipher_suites, + sizeof(u32) * local->hw.wiphy->n_cipher_suites, + GFP_KERNEL); + if (!suites) + return -ENOMEM; + + for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { + u32 suite = local->hw.wiphy->cipher_suites[r]; - /* Set up cipher suites if driver relies on mac80211 cipher defs */ - if (!local->hw.wiphy->cipher_suites && !cs) { + if (suite == WLAN_CIPHER_SUITE_WEP40 || + suite == WLAN_CIPHER_SUITE_WEP104) + continue; + suites[w++] = suite; + } + } else if (!local->hw.cipher_schemes) { + /* If the driver doesn't have cipher schemes, there's nothing + * else to do other than assign the (software supported and + * perhaps offloaded) cipher suites. + */ local->hw.wiphy->cipher_suites = cipher_suites; local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); if (!have_mfp) - local->hw.wiphy->n_cipher_suites--; + local->hw.wiphy->n_cipher_suites -= 4; if (!have_wep) { local->hw.wiphy->cipher_suites += 2; local->hw.wiphy->n_cipher_suites -= 2; } + /* not dynamically allocated, so just return */ return 0; - } + } else { + const struct ieee80211_cipher_scheme *cs; - if (!local->hw.wiphy->cipher_suites) { - /* - * Driver specifies cipher schemes only - * We start counting ciphers defined by schemes, TKIP and CCMP + cs = local->hw.cipher_schemes; + + /* Driver specifies cipher schemes only (but not cipher suites + * including the schemes) + * + * We start counting ciphers defined by schemes, TKIP, CCMP, + * CCMP-256, GCMP, and GCMP-256 */ - n_suites = local->hw.n_cipher_schemes + 2; + n_suites = local->hw.n_cipher_schemes + 5; /* check if we have WEP40 and WEP104 */ if (have_wep) n_suites += 2; - /* check if we have AES_CMAC */ + /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128, + * BIP-GMAC-256 + */ if (have_mfp) - n_suites++; + n_suites += 4; suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); if (!suites) return -ENOMEM; suites[w++] = WLAN_CIPHER_SUITE_CCMP; + suites[w++] = WLAN_CIPHER_SUITE_CCMP_256; suites[w++] = WLAN_CIPHER_SUITE_TKIP; + suites[w++] = WLAN_CIPHER_SUITE_GCMP; + suites[w++] = WLAN_CIPHER_SUITE_GCMP_256; if (have_wep) { suites[w++] = WLAN_CIPHER_SUITE_WEP40; suites[w++] = WLAN_CIPHER_SUITE_WEP104; } - if (have_mfp) + if (have_mfp) { suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; + suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256; + suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128; + suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; + } for (r = 0; r < local->hw.n_cipher_schemes; r++) suites[w++] = cs[r].cipher; - } else { - /* Driver provides cipher suites, but we need to exclude WEP */ - suites = kmemdup(local->hw.wiphy->cipher_suites, - sizeof(u32) * local->hw.wiphy->n_cipher_suites, - GFP_KERNEL); - if (!suites) - return -ENOMEM; - - for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { - u32 suite = local->hw.wiphy->cipher_suites[r]; - - if (suite == WLAN_CIPHER_SUITE_WEP40 || - suite == WLAN_CIPHER_SUITE_WEP104) - continue; - suites[w++] = suite; - } } local->hw.wiphy->cipher_suites = suites; @@ -1041,10 +1070,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ieee80211_max_network_latency; result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); - if (result) { - rtnl_lock(); + if (result) goto fail_pm_qos; - } #ifdef CONFIG_INET local->ifa_notifier.notifier_call = ieee80211_ifa_changed; @@ -1072,15 +1099,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) fail_ifa: pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); - rtnl_lock(); #endif fail_pm_qos: - ieee80211_led_exit(local); + rtnl_lock(); + rate_control_deinitialize(local); ieee80211_remove_interfaces(local); fail_rate: rtnl_unlock(); + ieee80211_led_exit(local); ieee80211_wep_free(local); - sta_info_stop(local); destroy_workqueue(local->workqueue); fail_workqueue: wiphy_unregister(local->hw.wiphy); @@ -1176,6 +1203,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) kfree(rcu_access_pointer(local->tx_latency)); + sta_info_stop(local); + wiphy_free(local->hw.wiphy); } EXPORT_SYMBOL(ieee80211_free_hw); |