|
|
@@ -5380,6 +5380,7 @@ static int nl80211_parse_mesh_config(struct genl_info *info,
|
|
|
{
|
|
|
struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
|
|
|
u32 mask = 0;
|
|
|
+ u16 ht_opmode;
|
|
|
|
|
|
#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
|
|
|
do { \
|
|
|
@@ -5471,9 +5472,36 @@ do { \
|
|
|
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
|
|
|
mask, NL80211_MESHCONF_RSSI_THRESHOLD,
|
|
|
nl80211_check_s32);
|
|
|
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
|
|
|
- mask, NL80211_MESHCONF_HT_OPMODE,
|
|
|
- nl80211_check_u16);
|
|
|
+ /*
|
|
|
+ * Check HT operation mode based on
|
|
|
+ * IEEE 802.11 2012 8.4.2.59 HT Operation element.
|
|
|
+ */
|
|
|
+ if (tb[NL80211_MESHCONF_HT_OPMODE]) {
|
|
|
+ ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
|
|
|
+
|
|
|
+ if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
|
|
|
+ IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
|
|
|
+ IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if ((ht_opmode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) &&
|
|
|
+ (ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION) {
|
|
|
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
|
|
|
+ case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
|
|
|
+ if (ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)
|
|
|
+ return -EINVAL;
|
|
|
+ break;
|
|
|
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
|
|
|
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
|
|
|
+ if (!(ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
|
|
|
+ return -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ cfg->ht_opmode = ht_opmode;
|
|
|
+ }
|
|
|
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
|
|
|
1, 65535, mask,
|
|
|
NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
|