|
@@ -200,6 +200,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|
[NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
|
|
[NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
|
|
.len = IEEE80211_MAX_DATA_LEN },
|
|
.len = IEEE80211_MAX_DATA_LEN },
|
|
[NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
|
|
[NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
|
|
|
|
+ [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
|
|
|
|
+ [NL80211_ATTR_HT_CAPABILITY_MASK] = {
|
|
|
|
+ .len = NL80211_HT_CAPABILITY_LEN
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
/* policy for the key attributes */
|
|
/* policy for the key attributes */
|
|
@@ -1032,6 +1036,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
|
|
|
|
|
NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features);
|
|
NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features);
|
|
|
|
|
|
|
|
+ if (dev->wiphy.ht_capa_mod_mask)
|
|
|
|
+ NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
|
|
|
|
+ sizeof(*dev->wiphy.ht_capa_mod_mask),
|
|
|
|
+ dev->wiphy.ht_capa_mod_mask);
|
|
|
|
+
|
|
return genlmsg_end(msg, hdr);
|
|
return genlmsg_end(msg, hdr);
|
|
|
|
|
|
nla_put_failure:
|
|
nla_put_failure:
|
|
@@ -4413,6 +4422,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
|
|
const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
|
|
const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
|
|
int err, ssid_len, ie_len = 0;
|
|
int err, ssid_len, ie_len = 0;
|
|
bool use_mfp = false;
|
|
bool use_mfp = false;
|
|
|
|
+ u32 flags = 0;
|
|
|
|
+ struct ieee80211_ht_cap *ht_capa = NULL;
|
|
|
|
+ struct ieee80211_ht_cap *ht_capa_mask = NULL;
|
|
|
|
|
|
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
|
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -4456,11 +4468,25 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
|
|
if (info->attrs[NL80211_ATTR_PREV_BSSID])
|
|
if (info->attrs[NL80211_ATTR_PREV_BSSID])
|
|
prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
|
|
prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
|
|
|
|
|
|
|
|
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
|
|
|
|
+ flags |= ASSOC_REQ_DISABLE_HT;
|
|
|
|
+
|
|
|
|
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
|
|
|
|
+ ht_capa_mask =
|
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
|
|
|
|
+
|
|
|
|
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
|
|
|
|
+ if (!ht_capa_mask)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
|
|
|
|
+ }
|
|
|
|
+
|
|
err = nl80211_crypto_settings(rdev, info, &crypto, 1);
|
|
err = nl80211_crypto_settings(rdev, info, &crypto, 1);
|
|
if (!err)
|
|
if (!err)
|
|
err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
|
|
err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
|
|
ssid, ssid_len, ie, ie_len, use_mfp,
|
|
ssid, ssid_len, ie, ie_len, use_mfp,
|
|
- &crypto);
|
|
|
|
|
|
+ &crypto, flags, ht_capa,
|
|
|
|
+ ht_capa_mask);
|
|
|
|
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
@@ -4950,6 +4976,22 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
|
return PTR_ERR(connkeys);
|
|
return PTR_ERR(connkeys);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
|
|
|
|
+ connect.flags |= ASSOC_REQ_DISABLE_HT;
|
|
|
|
+
|
|
|
|
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
|
|
|
|
+ memcpy(&connect.ht_capa_mask,
|
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
|
|
|
|
+ sizeof(connect.ht_capa_mask));
|
|
|
|
+
|
|
|
|
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
|
|
|
|
+ if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ memcpy(&connect.ht_capa,
|
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
|
|
|
|
+ sizeof(connect.ht_capa));
|
|
|
|
+ }
|
|
|
|
+
|
|
err = cfg80211_connect(rdev, dev, &connect, connkeys);
|
|
err = cfg80211_connect(rdev, dev, &connect, connkeys);
|
|
if (err)
|
|
if (err)
|
|
kfree(connkeys);
|
|
kfree(connkeys);
|