Previously, NL80211_MESHCONF_HT_OPMODE rejected correct flag
combination, ex) IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED |
IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT.

This was caused by simple comparison with value 16. This causes setting
non-existent flag (like 0x08) and invalid flag combinations. So this
commit implements some checks based on IEEE 802.11 2012 8.4.2.59 HT
Operation element.

Signed-off-by: Masashi Honma <masashi.ho...@gmail.com>
---
 net/wireless/nl80211.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 46417f9..b2af600 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5471,9 +5471,49 @@ 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,
+       FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0,
+                                 IEEE80211_HT_OP_MODE_PROTECTION |
+                                 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
+                                 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT,
                                  mask, NL80211_MESHCONF_HT_OPMODE,
                                  nl80211_check_u16);
+       if (tb[NL80211_MESHCONF_HT_OPMODE]) {
+               /*
+                * Check HT operation mode based on IEEE 802.11 2012 8.4.2.59
+                * HT Operation element.
+                */
+               if (cfg->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 ((cfg->ht_opmode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) &&
+                   (cfg->ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
+                       return -EINVAL;
+
+               switch (cfg->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION) {
+               case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+                       if (cfg->ht_opmode &
+                           IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)
+                               return -EINVAL;
+                       break;
+               case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+                       if (!(cfg->ht_opmode &
+                           IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
+                               return -EINVAL;
+                       break;
+               case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+                       if (cfg->ht_opmode &
+                           IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)
+                               return -EINVAL;
+                       break;
+               case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+                       if (!(cfg->ht_opmode &
+                           IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
+                               return -EINVAL;
+                       break;
+               }
+       }
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
                                  1, 65535, mask,
                                  NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to