aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-03-26 10:17:18 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-16 09:29:45 -0400
commit1b3a2e494bc793445f576c5476e9767cf7621684 (patch)
tree0a42b6e5a98e1e6a686c500661db79ae092f336d
parent85220d71bf3ca1ba9129e0744247ae5f61bec559 (diff)
mac80211: handle extended channel switch announcement
Handle the (public) extended channel switch announcement action frames. Parts of the data in these frames isn't really in IEs, but put it into the elems struct anyway to simplify the handling. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/linux/ieee80211.h6
-rw-r--r--net/mac80211/mlme.c31
-rw-r--r--net/mac80211/rx.c16
3 files changed, 49 insertions, 4 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 95621528436c..ce07161c8735 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -866,6 +866,11 @@ struct ieee80211_mgmt {
866 } __packed chan_switch; 866 } __packed chan_switch;
867 struct{ 867 struct{
868 u8 action_code; 868 u8 action_code;
869 struct ieee80211_ext_chansw_ie data;
870 u8 variable[0];
871 } __packed ext_chan_switch;
872 struct{
873 u8 action_code;
869 u8 dialog_token; 874 u8 dialog_token;
870 u8 element_id; 875 u8 element_id;
871 u8 length; 876 u8 length;
@@ -1816,6 +1821,7 @@ enum ieee80211_key_len {
1816 1821
1817/* Public action codes */ 1822/* Public action codes */
1818enum ieee80211_pub_actioncode { 1823enum ieee80211_pub_actioncode {
1824 WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
1819 WLAN_PUB_ACTION_TDLS_DISCOVER_RES = 14, 1825 WLAN_PUB_ACTION_TDLS_DISCOVER_RES = 14,
1820}; 1826};
1821 1827
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index bd581a80e4b7..c53aedb47a6a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3100,6 +3100,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
3100 enum rx_mgmt_action rma = RX_MGMT_NONE; 3100 enum rx_mgmt_action rma = RX_MGMT_NONE;
3101 u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; 3101 u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
3102 u16 fc; 3102 u16 fc;
3103 struct ieee802_11_elems elems;
3104 int ies_len;
3103 3105
3104 rx_status = (struct ieee80211_rx_status *) skb->cb; 3106 rx_status = (struct ieee80211_rx_status *) skb->cb;
3105 mgmt = (struct ieee80211_mgmt *) skb->data; 3107 mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -3130,10 +3132,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
3130 break; 3132 break;
3131 case IEEE80211_STYPE_ACTION: 3133 case IEEE80211_STYPE_ACTION:
3132 if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) { 3134 if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
3133 struct ieee802_11_elems elems; 3135 ies_len = skb->len -
3134 int ies_len = skb->len - 3136 offsetof(struct ieee80211_mgmt,
3135 offsetof(struct ieee80211_mgmt, 3137 u.action.u.chan_switch.variable);
3136 u.action.u.chan_switch.variable);
3137 3138
3138 if (ies_len < 0) 3139 if (ies_len < 0)
3139 break; 3140 break;
@@ -3148,6 +3149,28 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
3148 ieee80211_sta_process_chanswitch(sdata, 3149 ieee80211_sta_process_chanswitch(sdata,
3149 rx_status->mactime, 3150 rx_status->mactime,
3150 &elems); 3151 &elems);
3152 } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
3153 ies_len = skb->len -
3154 offsetof(struct ieee80211_mgmt,
3155 u.action.u.ext_chan_switch.variable);
3156
3157 if (ies_len < 0)
3158 break;
3159
3160 ieee802_11_parse_elems(
3161 mgmt->u.action.u.ext_chan_switch.variable,
3162 ies_len, &elems);
3163
3164 if (elems.parse_error)
3165 break;
3166
3167 /* for the handling code pretend this was also an IE */
3168 elems.ext_chansw_ie =
3169 &mgmt->u.action.u.ext_chan_switch.data;
3170
3171 ieee80211_sta_process_chanswitch(sdata,
3172 rx_status->mactime,
3173 &elems);
3151 } 3174 }
3152 break; 3175 break;
3153 } 3176 }
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e9825f15c14c..643fcf7c9dcd 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2424,6 +2424,22 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2424 } 2424 }
2425 2425
2426 break; 2426 break;
2427 case WLAN_CATEGORY_PUBLIC:
2428 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
2429 goto invalid;
2430 if (sdata->vif.type != NL80211_IFTYPE_STATION)
2431 break;
2432 if (!rx->sta)
2433 break;
2434 if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid))
2435 break;
2436 if (mgmt->u.action.u.ext_chan_switch.action_code !=
2437 WLAN_PUB_ACTION_EXT_CHANSW_ANN)
2438 break;
2439 if (len < offsetof(struct ieee80211_mgmt,
2440 u.action.u.ext_chan_switch.variable))
2441 goto invalid;
2442 goto queue;
2427 case WLAN_CATEGORY_VHT: 2443 case WLAN_CATEGORY_VHT:
2428 if (sdata->vif.type != NL80211_IFTYPE_STATION && 2444 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
2429 sdata->vif.type != NL80211_IFTYPE_MESH_POINT && 2445 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&