Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+49 -4
+6
include/linux/ieee80211.h
··· 866 866 } __packed chan_switch; 867 867 struct{ 868 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 874 u8 dialog_token; 870 875 u8 element_id; 871 876 u8 length; ··· 1821 1816 1822 1817 /* Public action codes */ 1823 1818 enum ieee80211_pub_actioncode { 1819 + WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4, 1824 1820 WLAN_PUB_ACTION_TDLS_DISCOVER_RES = 14, 1825 1821 }; 1826 1822
+27 -4
net/mac80211/mlme.c
··· 3100 3100 enum rx_mgmt_action rma = RX_MGMT_NONE; 3101 3101 u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; 3102 3102 u16 fc; 3103 + struct ieee802_11_elems elems; 3104 + int ies_len; 3103 3105 3104 3106 rx_status = (struct ieee80211_rx_status *) skb->cb; 3105 3107 mgmt = (struct ieee80211_mgmt *) skb->data; ··· 3132 3130 break; 3133 3131 case IEEE80211_STYPE_ACTION: 3134 3132 if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) { 3135 - struct ieee802_11_elems elems; 3136 - int ies_len = skb->len - 3137 - offsetof(struct ieee80211_mgmt, 3138 - u.action.u.chan_switch.variable); 3133 + ies_len = skb->len - 3134 + offsetof(struct ieee80211_mgmt, 3135 + u.action.u.chan_switch.variable); 3139 3136 3140 3137 if (ies_len < 0) 3141 3138 break; ··· 3145 3144 3146 3145 if (elems.parse_error) 3147 3146 break; 3147 + 3148 + ieee80211_sta_process_chanswitch(sdata, 3149 + rx_status->mactime, 3150 + &elems); 3151 + } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { 3152 + ies_len = skb->len - 3153 + offsetof(struct ieee80211_mgmt, 3154 + u.action.u.ext_chan_switch.variable); 3155 + 3156 + if (ies_len < 0) 3157 + break; 3158 + 3159 + ieee802_11_parse_elems( 3160 + mgmt->u.action.u.ext_chan_switch.variable, 3161 + ies_len, &elems); 3162 + 3163 + if (elems.parse_error) 3164 + break; 3165 + 3166 + /* for the handling code pretend this was also an IE */ 3167 + elems.ext_chansw_ie = 3168 + &mgmt->u.action.u.ext_chan_switch.data; 3148 3169 3149 3170 ieee80211_sta_process_chanswitch(sdata, 3150 3171 rx_status->mactime,
+16
net/mac80211/rx.c
··· 2424 2424 } 2425 2425 2426 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 2443 case WLAN_CATEGORY_VHT: 2428 2444 if (sdata->vif.type != NL80211_IFTYPE_STATION && 2429 2445 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&