diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 279 |
1 files changed, 178 insertions, 101 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fb123e2e081a..f407427c642f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "wpa.h" | 28 | #include "wpa.h" |
29 | #include "tkip.h" | 29 | #include "tkip.h" |
30 | #include "wme.h" | 30 | #include "wme.h" |
31 | #include "rate.h" | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * monitor mode reception | 34 | * monitor mode reception |
@@ -748,10 +749,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
748 | struct ieee80211_local *local = rx->local; | 749 | struct ieee80211_local *local = rx->local; |
749 | struct ieee80211_hw *hw = &local->hw; | 750 | struct ieee80211_hw *hw = &local->hw; |
750 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 751 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
752 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
751 | struct sta_info *sta = rx->sta; | 753 | struct sta_info *sta = rx->sta; |
752 | struct tid_ampdu_rx *tid_agg_rx; | 754 | struct tid_ampdu_rx *tid_agg_rx; |
753 | u16 sc; | 755 | u16 sc; |
754 | int tid; | 756 | u8 tid, ack_policy; |
755 | 757 | ||
756 | if (!ieee80211_is_data_qos(hdr->frame_control)) | 758 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
757 | goto dont_reorder; | 759 | goto dont_reorder; |
@@ -764,6 +766,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
764 | if (!sta) | 766 | if (!sta) |
765 | goto dont_reorder; | 767 | goto dont_reorder; |
766 | 768 | ||
769 | ack_policy = *ieee80211_get_qos_ctl(hdr) & | ||
770 | IEEE80211_QOS_CTL_ACK_POLICY_MASK; | ||
767 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 771 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
768 | 772 | ||
769 | tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); | 773 | tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); |
@@ -774,6 +778,15 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
774 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 778 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
775 | goto dont_reorder; | 779 | goto dont_reorder; |
776 | 780 | ||
781 | /* not part of a BA session */ | ||
782 | if (ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK && | ||
783 | ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) | ||
784 | goto dont_reorder; | ||
785 | |||
786 | /* not actually part of this BA session */ | ||
787 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
788 | goto dont_reorder; | ||
789 | |||
777 | /* new, potentially un-ordered, ampdu frame - process it */ | 790 | /* new, potentially un-ordered, ampdu frame - process it */ |
778 | 791 | ||
779 | /* reset session timer */ | 792 | /* reset session timer */ |
@@ -858,6 +871,13 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
858 | rx->sdata->control_port_protocol) | 871 | rx->sdata->control_port_protocol) |
859 | return RX_CONTINUE; | 872 | return RX_CONTINUE; |
860 | } | 873 | } |
874 | |||
875 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && | ||
876 | cfg80211_rx_spurious_frame(rx->sdata->dev, | ||
877 | hdr->addr2, | ||
878 | GFP_ATOMIC)) | ||
879 | return RX_DROP_UNUSABLE; | ||
880 | |||
861 | return RX_DROP_MONITOR; | 881 | return RX_DROP_MONITOR; |
862 | } | 882 | } |
863 | 883 | ||
@@ -1327,15 +1347,20 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1327 | 1347 | ||
1328 | /* | 1348 | /* |
1329 | * If we receive a 4-addr nullfunc frame from a STA | 1349 | * If we receive a 4-addr nullfunc frame from a STA |
1330 | * that was not moved to a 4-addr STA vlan yet, drop | 1350 | * that was not moved to a 4-addr STA vlan yet send |
1331 | * the frame to the monitor interface, to make sure | 1351 | * the event to userspace and for older hostapd drop |
1332 | * that hostapd sees it | 1352 | * the frame to the monitor interface. |
1333 | */ | 1353 | */ |
1334 | if (ieee80211_has_a4(hdr->frame_control) && | 1354 | if (ieee80211_has_a4(hdr->frame_control) && |
1335 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1355 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1336 | (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | 1356 | (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
1337 | !rx->sdata->u.vlan.sta))) | 1357 | !rx->sdata->u.vlan.sta))) { |
1358 | if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT)) | ||
1359 | cfg80211_rx_unexpected_4addr_frame( | ||
1360 | rx->sdata->dev, sta->sta.addr, | ||
1361 | GFP_ATOMIC); | ||
1338 | return RX_DROP_MONITOR; | 1362 | return RX_DROP_MONITOR; |
1363 | } | ||
1339 | /* | 1364 | /* |
1340 | * Update counter and free packet here to avoid | 1365 | * Update counter and free packet here to avoid |
1341 | * counting this as a dropped packed. | 1366 | * counting this as a dropped packed. |
@@ -1551,25 +1576,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1551 | return RX_CONTINUE; | 1576 | return RX_CONTINUE; |
1552 | } | 1577 | } |
1553 | 1578 | ||
1554 | static ieee80211_rx_result debug_noinline | ||
1555 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | ||
1556 | { | ||
1557 | u8 *data = rx->skb->data; | ||
1558 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; | ||
1559 | |||
1560 | if (!ieee80211_is_data_qos(hdr->frame_control)) | ||
1561 | return RX_CONTINUE; | ||
1562 | |||
1563 | /* remove the qos control field, update frame type and meta-data */ | ||
1564 | memmove(data + IEEE80211_QOS_CTL_LEN, data, | ||
1565 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); | ||
1566 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); | ||
1567 | /* change frame type to non QOS */ | ||
1568 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | ||
1569 | |||
1570 | return RX_CONTINUE; | ||
1571 | } | ||
1572 | |||
1573 | static int | 1579 | static int |
1574 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | 1580 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) |
1575 | { | 1581 | { |
@@ -1802,7 +1808,12 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1802 | } | 1808 | } |
1803 | 1809 | ||
1804 | if (xmit_skb) { | 1810 | if (xmit_skb) { |
1805 | /* send to wireless media */ | 1811 | /* |
1812 | * Send to wireless media and increase priority by 256 to | ||
1813 | * keep the received priority instead of reclassifying | ||
1814 | * the frame (see cfg80211_classify8021d). | ||
1815 | */ | ||
1816 | xmit_skb->priority += 256; | ||
1806 | xmit_skb->protocol = htons(ETH_P_802_3); | 1817 | xmit_skb->protocol = htons(ETH_P_802_3); |
1807 | skb_reset_network_header(xmit_skb); | 1818 | skb_reset_network_header(xmit_skb); |
1808 | skb_reset_mac_header(xmit_skb); | 1819 | skb_reset_mac_header(xmit_skb); |
@@ -1871,13 +1882,16 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1871 | static ieee80211_rx_result | 1882 | static ieee80211_rx_result |
1872 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | 1883 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1873 | { | 1884 | { |
1874 | struct ieee80211_hdr *hdr; | 1885 | struct ieee80211_hdr *fwd_hdr, *hdr; |
1886 | struct ieee80211_tx_info *info; | ||
1875 | struct ieee80211s_hdr *mesh_hdr; | 1887 | struct ieee80211s_hdr *mesh_hdr; |
1876 | unsigned int hdrlen; | ||
1877 | struct sk_buff *skb = rx->skb, *fwd_skb; | 1888 | struct sk_buff *skb = rx->skb, *fwd_skb; |
1878 | struct ieee80211_local *local = rx->local; | 1889 | struct ieee80211_local *local = rx->local; |
1879 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1890 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1880 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 1891 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
1892 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1893 | __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); | ||
1894 | u16 q, hdrlen; | ||
1881 | 1895 | ||
1882 | hdr = (struct ieee80211_hdr *) skb->data; | 1896 | hdr = (struct ieee80211_hdr *) skb->data; |
1883 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1897 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -1893,14 +1907,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1893 | return RX_CONTINUE; | 1907 | return RX_CONTINUE; |
1894 | 1908 | ||
1895 | if (!mesh_hdr->ttl) | 1909 | if (!mesh_hdr->ttl) |
1896 | /* illegal frame */ | ||
1897 | return RX_DROP_MONITOR; | ||
1898 | |||
1899 | if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) { | ||
1900 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1901 | dropped_frames_congestion); | ||
1902 | return RX_DROP_MONITOR; | 1910 | return RX_DROP_MONITOR; |
1903 | } | ||
1904 | 1911 | ||
1905 | if (mesh_hdr->flags & MESH_FLAGS_AE) { | 1912 | if (mesh_hdr->flags & MESH_FLAGS_AE) { |
1906 | struct mesh_path *mppath; | 1913 | struct mesh_path *mppath; |
@@ -1933,60 +1940,50 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1933 | compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) | 1940 | compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) |
1934 | return RX_CONTINUE; | 1941 | return RX_CONTINUE; |
1935 | 1942 | ||
1936 | mesh_hdr->ttl--; | 1943 | q = ieee80211_select_queue_80211(local, skb, hdr); |
1944 | if (ieee80211_queue_stopped(&local->hw, q)) { | ||
1945 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); | ||
1946 | return RX_DROP_MONITOR; | ||
1947 | } | ||
1948 | skb_set_queue_mapping(skb, q); | ||
1937 | 1949 | ||
1938 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { | 1950 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
1939 | if (!mesh_hdr->ttl) | 1951 | goto out; |
1940 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, | 1952 | |
1941 | dropped_frames_ttl); | 1953 | if (!--mesh_hdr->ttl) { |
1942 | else { | 1954 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); |
1943 | struct ieee80211_hdr *fwd_hdr; | 1955 | return RX_DROP_MONITOR; |
1944 | struct ieee80211_tx_info *info; | 1956 | } |
1945 | 1957 | ||
1946 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | 1958 | fwd_skb = skb_copy(skb, GFP_ATOMIC); |
1947 | 1959 | if (!fwd_skb) { | |
1948 | if (!fwd_skb && net_ratelimit()) | 1960 | if (net_ratelimit()) |
1949 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1961 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1950 | sdata->name); | 1962 | sdata->name); |
1951 | if (!fwd_skb) | 1963 | goto out; |
1952 | goto out; | ||
1953 | |||
1954 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | ||
1955 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
1956 | info = IEEE80211_SKB_CB(fwd_skb); | ||
1957 | memset(info, 0, sizeof(*info)); | ||
1958 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1959 | info->control.vif = &rx->sdata->vif; | ||
1960 | if (is_multicast_ether_addr(fwd_hdr->addr1)) { | ||
1961 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1962 | fwded_mcast); | ||
1963 | skb_set_queue_mapping(fwd_skb, | ||
1964 | ieee80211_select_queue(sdata, fwd_skb)); | ||
1965 | ieee80211_set_qos_hdr(sdata, fwd_skb); | ||
1966 | } else { | ||
1967 | int err; | ||
1968 | /* | ||
1969 | * Save TA to addr1 to send TA a path error if a | ||
1970 | * suitable next hop is not found | ||
1971 | */ | ||
1972 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, | ||
1973 | ETH_ALEN); | ||
1974 | err = mesh_nexthop_lookup(fwd_skb, sdata); | ||
1975 | /* Failed to immediately resolve next hop: | ||
1976 | * fwded frame was dropped or will be added | ||
1977 | * later to the pending skb queue. */ | ||
1978 | if (err) | ||
1979 | return RX_DROP_MONITOR; | ||
1980 | |||
1981 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1982 | fwded_unicast); | ||
1983 | } | ||
1984 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1985 | fwded_frames); | ||
1986 | ieee80211_add_pending_skb(local, fwd_skb); | ||
1987 | } | ||
1988 | } | 1964 | } |
1989 | 1965 | ||
1966 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | ||
1967 | info = IEEE80211_SKB_CB(fwd_skb); | ||
1968 | memset(info, 0, sizeof(*info)); | ||
1969 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1970 | info->control.vif = &rx->sdata->vif; | ||
1971 | info->control.jiffies = jiffies; | ||
1972 | if (is_multicast_ether_addr(fwd_hdr->addr1)) { | ||
1973 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); | ||
1974 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
1975 | } else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { | ||
1976 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); | ||
1977 | } else { | ||
1978 | /* unable to resolve next hop */ | ||
1979 | mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, | ||
1980 | 0, reason, fwd_hdr->addr2, sdata); | ||
1981 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); | ||
1982 | return RX_DROP_MONITOR; | ||
1983 | } | ||
1984 | |||
1985 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); | ||
1986 | ieee80211_add_pending_skb(local, fwd_skb); | ||
1990 | out: | 1987 | out: |
1991 | if (is_multicast_ether_addr(hdr->addr1) || | 1988 | if (is_multicast_ether_addr(hdr->addr1) || |
1992 | sdata->dev->flags & IFF_PROMISC) | 1989 | sdata->dev->flags & IFF_PROMISC) |
@@ -2014,12 +2011,17 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2014 | return RX_DROP_MONITOR; | 2011 | return RX_DROP_MONITOR; |
2015 | 2012 | ||
2016 | /* | 2013 | /* |
2017 | * Allow the cooked monitor interface of an AP to see 4-addr frames so | 2014 | * Send unexpected-4addr-frame event to hostapd. For older versions, |
2018 | * that a 4-addr station can be detected and moved into a separate VLAN | 2015 | * also drop the frame to cooked monitor interfaces. |
2019 | */ | 2016 | */ |
2020 | if (ieee80211_has_a4(hdr->frame_control) && | 2017 | if (ieee80211_has_a4(hdr->frame_control) && |
2021 | sdata->vif.type == NL80211_IFTYPE_AP) | 2018 | sdata->vif.type == NL80211_IFTYPE_AP) { |
2019 | if (rx->sta && | ||
2020 | !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) | ||
2021 | cfg80211_rx_unexpected_4addr_frame( | ||
2022 | rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); | ||
2022 | return RX_DROP_MONITOR; | 2023 | return RX_DROP_MONITOR; |
2024 | } | ||
2023 | 2025 | ||
2024 | err = __ieee80211_data_to_8023(rx, &port_control); | 2026 | err = __ieee80211_data_to_8023(rx, &port_control); |
2025 | if (unlikely(err)) | 2027 | if (unlikely(err)) |
@@ -2174,6 +2176,18 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | |||
2174 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | 2176 | if (!ieee80211_is_mgmt(mgmt->frame_control)) |
2175 | return RX_DROP_MONITOR; | 2177 | return RX_DROP_MONITOR; |
2176 | 2178 | ||
2179 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && | ||
2180 | ieee80211_is_beacon(mgmt->frame_control) && | ||
2181 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { | ||
2182 | struct ieee80211_rx_status *status; | ||
2183 | |||
2184 | status = IEEE80211_SKB_RXCB(rx->skb); | ||
2185 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, | ||
2186 | rx->skb->data, rx->skb->len, | ||
2187 | status->freq, GFP_ATOMIC); | ||
2188 | rx->flags |= IEEE80211_RX_BEACON_REPORTED; | ||
2189 | } | ||
2190 | |||
2177 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | 2191 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
2178 | return RX_DROP_MONITOR; | 2192 | return RX_DROP_MONITOR; |
2179 | 2193 | ||
@@ -2206,16 +2220,69 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2206 | return RX_DROP_UNUSABLE; | 2220 | return RX_DROP_UNUSABLE; |
2207 | 2221 | ||
2208 | switch (mgmt->u.action.category) { | 2222 | switch (mgmt->u.action.category) { |
2223 | case WLAN_CATEGORY_HT: | ||
2224 | /* reject HT action frames from stations not supporting HT */ | ||
2225 | if (!rx->sta->sta.ht_cap.ht_supported) | ||
2226 | goto invalid; | ||
2227 | |||
2228 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
2229 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | ||
2230 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
2231 | sdata->vif.type != NL80211_IFTYPE_AP && | ||
2232 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
2233 | break; | ||
2234 | |||
2235 | /* verify action & smps_control are present */ | ||
2236 | if (len < IEEE80211_MIN_ACTION_SIZE + 2) | ||
2237 | goto invalid; | ||
2238 | |||
2239 | switch (mgmt->u.action.u.ht_smps.action) { | ||
2240 | case WLAN_HT_ACTION_SMPS: { | ||
2241 | struct ieee80211_supported_band *sband; | ||
2242 | u8 smps; | ||
2243 | |||
2244 | /* convert to HT capability */ | ||
2245 | switch (mgmt->u.action.u.ht_smps.smps_control) { | ||
2246 | case WLAN_HT_SMPS_CONTROL_DISABLED: | ||
2247 | smps = WLAN_HT_CAP_SM_PS_DISABLED; | ||
2248 | break; | ||
2249 | case WLAN_HT_SMPS_CONTROL_STATIC: | ||
2250 | smps = WLAN_HT_CAP_SM_PS_STATIC; | ||
2251 | break; | ||
2252 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | ||
2253 | smps = WLAN_HT_CAP_SM_PS_DYNAMIC; | ||
2254 | break; | ||
2255 | default: | ||
2256 | goto invalid; | ||
2257 | } | ||
2258 | smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
2259 | |||
2260 | /* if no change do nothing */ | ||
2261 | if ((rx->sta->sta.ht_cap.cap & | ||
2262 | IEEE80211_HT_CAP_SM_PS) == smps) | ||
2263 | goto handled; | ||
2264 | |||
2265 | rx->sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
2266 | rx->sta->sta.ht_cap.cap |= smps; | ||
2267 | |||
2268 | sband = rx->local->hw.wiphy->bands[status->band]; | ||
2269 | |||
2270 | rate_control_rate_update(local, sband, rx->sta, | ||
2271 | IEEE80211_RC_SMPS_CHANGED, | ||
2272 | local->_oper_channel_type); | ||
2273 | goto handled; | ||
2274 | } | ||
2275 | default: | ||
2276 | goto invalid; | ||
2277 | } | ||
2278 | |||
2279 | break; | ||
2209 | case WLAN_CATEGORY_BACK: | 2280 | case WLAN_CATEGORY_BACK: |
2210 | /* | ||
2211 | * The aggregation code is not prepared to handle | ||
2212 | * anything but STA/AP due to the BSSID handling; | ||
2213 | * IBSS could work in the code but isn't supported | ||
2214 | * by drivers or the standard. | ||
2215 | */ | ||
2216 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 2281 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
2282 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | ||
2217 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 2283 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
2218 | sdata->vif.type != NL80211_IFTYPE_AP) | 2284 | sdata->vif.type != NL80211_IFTYPE_AP && |
2285 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
2219 | break; | 2286 | break; |
2220 | 2287 | ||
2221 | /* verify action_code is present */ | 2288 | /* verify action_code is present */ |
@@ -2493,6 +2560,10 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2493 | goto out_free_skb; | 2560 | goto out_free_skb; |
2494 | rx->flags |= IEEE80211_RX_CMNTR; | 2561 | rx->flags |= IEEE80211_RX_CMNTR; |
2495 | 2562 | ||
2563 | /* If there are no cooked monitor interfaces, just free the SKB */ | ||
2564 | if (!local->cooked_mntrs) | ||
2565 | goto out_free_skb; | ||
2566 | |||
2496 | if (skb_headroom(skb) < sizeof(*rthdr) && | 2567 | if (skb_headroom(skb) < sizeof(*rthdr) && |
2497 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) | 2568 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) |
2498 | goto out_free_skb; | 2569 | goto out_free_skb; |
@@ -2628,7 +2699,6 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2628 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) | 2699 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
2629 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2700 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2630 | #endif | 2701 | #endif |
2631 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | ||
2632 | CALL_RXH(ieee80211_rx_h_amsdu) | 2702 | CALL_RXH(ieee80211_rx_h_amsdu) |
2633 | CALL_RXH(ieee80211_rx_h_data) | 2703 | CALL_RXH(ieee80211_rx_h_data) |
2634 | CALL_RXH(ieee80211_rx_h_ctrl); | 2704 | CALL_RXH(ieee80211_rx_h_ctrl); |
@@ -2748,8 +2818,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2748 | rate_idx = 0; /* TODO: HT rates */ | 2818 | rate_idx = 0; /* TODO: HT rates */ |
2749 | else | 2819 | else |
2750 | rate_idx = status->rate_idx; | 2820 | rate_idx = status->rate_idx; |
2751 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, | 2821 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, |
2752 | hdr->addr2, BIT(rate_idx), GFP_ATOMIC); | 2822 | BIT(rate_idx)); |
2753 | } | 2823 | } |
2754 | break; | 2824 | break; |
2755 | case NL80211_IFTYPE_MESH_POINT: | 2825 | case NL80211_IFTYPE_MESH_POINT: |
@@ -2770,10 +2840,17 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2770 | return 0; | 2840 | return 0; |
2771 | } else if (!ieee80211_bssid_match(bssid, | 2841 | } else if (!ieee80211_bssid_match(bssid, |
2772 | sdata->vif.addr)) { | 2842 | sdata->vif.addr)) { |
2843 | /* | ||
2844 | * Accept public action frames even when the | ||
2845 | * BSSID doesn't match, this is used for P2P | ||
2846 | * and location updates. Note that mac80211 | ||
2847 | * itself never looks at these frames. | ||
2848 | */ | ||
2849 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | ||
2850 | ieee80211_is_public_action(hdr, skb->len)) | ||
2851 | return 1; | ||
2773 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | 2852 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && |
2774 | !ieee80211_is_beacon(hdr->frame_control) && | 2853 | !ieee80211_is_beacon(hdr->frame_control)) |
2775 | !(ieee80211_is_action(hdr->frame_control) && | ||
2776 | sdata->vif.p2p)) | ||
2777 | return 0; | 2854 | return 0; |
2778 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2855 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2779 | } | 2856 | } |