cfg80211: add cipher capabilities
authorJohannes Berg <johannes@sipsolutions.net>
Thu, 2 Apr 2009 18:14:06 +0000 (20:14 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 22 Apr 2009 20:54:40 +0000 (16:54 -0400)
This adds the necessary code and fields to let drivers specify
their cipher capabilities and exports them to userspace. Also
update mac80211 to export the ciphers it has.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/linux/nl80211.h
include/net/wireless.h
net/mac80211/main.c
net/wireless/nl80211.c

index 05ba353..c014238 100644 (file)
@@ -453,6 +453,9 @@ enum nl80211_commands {
  *     attributes consists of a nested attribute containing
  *     NL80211_FREQUENCY_ATTR_*
  *
+ * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported
+ *     cipher suites
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -540,6 +543,7 @@ enum nl80211_attrs {
        NL80211_ATTR_KEY_TYPE,
 
        NL80211_ATTR_MAX_SCAN_IE_LEN,
+       NL80211_ATTR_CIPHER_SUITES,
 
        NL80211_ATTR_FREQ_BEFORE,
        NL80211_ATTR_FREQ_AFTER,
index 2bcdeda..44c2642 100644 (file)
@@ -205,6 +205,8 @@ struct ieee80211_supported_band {
  *     on the reg_notifier() if it chooses to ignore future
  *     regulatory domain changes caused by other drivers.
  * @signal_type: signal type reported in &struct cfg80211_bss.
+ * @cipher_suites: supported cipher suites
+ * @n_cipher_suites: number of supported cipher suites
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
@@ -224,6 +226,9 @@ struct wiphy {
        u8 max_scan_ssids;
        u16 max_scan_ie_len;
 
+       int n_cipher_suites;
+       const u32 *cipher_suites;
+
        /* If multiple wiphys are registered and you're handed e.g.
         * a regular netdev with assigned ieee80211_ptr, you won't
         * know whether it points to a wiphy your driver has registered
index 679b3a1..c1145be 100644 (file)
@@ -823,6 +823,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        struct ieee80211_master_priv *mpriv;
        int channels, i, j, max_bitrates;
        bool supp_ht;
+       static const u32 cipher_suites[] = {
+               WLAN_CIPHER_SUITE_WEP40,
+               WLAN_CIPHER_SUITE_WEP104,
+               WLAN_CIPHER_SUITE_TKIP,
+               WLAN_CIPHER_SUITE_CCMP,
+
+               /* keep last -- depends on hw flags! */
+               WLAN_CIPHER_SUITE_AES_CMAC
+       };
 
        /*
         * generic code guarantees at least one band,
@@ -894,6 +903,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (local->hw.wiphy->max_scan_ie_len)
                local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
 
+       local->hw.wiphy->cipher_suites = cipher_suites;
+       local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+       if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
+               local->hw.wiphy->n_cipher_suites--;
+
        result = wiphy_register(local->hw.wiphy);
        if (result < 0)
                goto fail_wiphy_register;
index 85b5aa3..d33cab0 100644 (file)
@@ -208,6 +208,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
        NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
                    dev->wiphy.max_scan_ie_len);
 
+       NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
+               sizeof(u32) * dev->wiphy.n_cipher_suites,
+               dev->wiphy.cipher_suites);
+
        nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
        if (!nl_modes)
                goto nla_put_failure;
@@ -979,7 +983,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *drv;
-       int err;
+       int err, i;
        struct net_device *dev;
        struct key_params params;
        u8 key_idx = 0;
@@ -1048,6 +1052,14 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto unlock_rtnl;
 
+       for (i = 0; i < drv->wiphy.n_cipher_suites; i++)
+               if (params.cipher == drv->wiphy.cipher_suites[i])
+                       break;
+       if (i == drv->wiphy.n_cipher_suites) {
+               err = -EINVAL;
+               goto out;
+       }
+
        if (!drv->ops->add_key) {
                err = -EOPNOTSUPP;
                goto out;