summaryrefslogtreecommitdiff
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2be5b7d69ad7..57832eb44f3e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -28,6 +28,7 @@
#include "wpa.h"
#include "tkip.h"
#include "wme.h"
+#include "rate.h"
/*
* monitor mode reception
@@ -2233,6 +2234,63 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
return RX_DROP_UNUSABLE;
switch (mgmt->u.action.category) {
+ case WLAN_CATEGORY_HT:
+ /* reject HT action frames from stations not supporting HT */
+ if (!rx->sta->sta.ht_cap.ht_supported)
+ goto invalid;
+
+ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+ sdata->vif.type != NL80211_IFTYPE_AP &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ break;
+
+ /* verify action & smps_control are present */
+ if (len < IEEE80211_MIN_ACTION_SIZE + 2)
+ goto invalid;
+
+ switch (mgmt->u.action.u.ht_smps.action) {
+ case WLAN_HT_ACTION_SMPS: {
+ struct ieee80211_supported_band *sband;
+ u8 smps;
+
+ /* convert to HT capability */
+ switch (mgmt->u.action.u.ht_smps.smps_control) {
+ case WLAN_HT_SMPS_CONTROL_DISABLED:
+ smps = WLAN_HT_CAP_SM_PS_DISABLED;
+ break;
+ case WLAN_HT_SMPS_CONTROL_STATIC:
+ smps = WLAN_HT_CAP_SM_PS_STATIC;
+ break;
+ case WLAN_HT_SMPS_CONTROL_DYNAMIC:
+ smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
+ break;
+ default:
+ goto invalid;
+ }
+ smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+ /* if no change do nothing */
+ if ((rx->sta->sta.ht_cap.cap &
+ IEEE80211_HT_CAP_SM_PS) == smps)
+ goto handled;
+
+ rx->sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS;
+ rx->sta->sta.ht_cap.cap |= smps;
+
+ sband = rx->local->hw.wiphy->bands[status->band];
+
+ rate_control_rate_update(local, sband, rx->sta,
+ IEEE80211_RC_SMPS_CHANGED,
+ local->_oper_channel_type);
+ goto handled;
+ }
+ default:
+ goto invalid;
+ }
+
+ break;
case WLAN_CATEGORY_BACK:
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&