diff options
-rw-r--r-- | include/linux/ieee80211.h | 6 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 31 | ||||
-rw-r--r-- | net/mac80211/rx.c | 16 |
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 */ |
1818 | enum ieee80211_pub_actioncode { | 1823 | enum 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 && |