diff options
Diffstat (limited to 'net/mac80211/rx.c')
| -rw-r--r-- | net/mac80211/rx.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3adcda502b7..40fe2798cbf 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -1950,8 +1950,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 1950 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1950 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
| 1951 | break; | 1951 | break; |
| 1952 | 1952 | ||
| 1953 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 1953 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
| 1954 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 1954 | skb_queue_tail(&sdata->skb_queue, rx->skb); |
| 1955 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
| 1956 | return RX_QUEUED; | ||
| 1957 | } | ||
| 1955 | 1958 | ||
| 1956 | switch (mgmt->u.action.u.addba_req.action_code) { | 1959 | switch (mgmt->u.action.u.addba_req.action_code) { |
| 1957 | case WLAN_ACTION_ADDBA_REQ: | 1960 | case WLAN_ACTION_ADDBA_REQ: |
| @@ -2003,7 +2006,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 2003 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) | 2006 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) |
| 2004 | break; | 2007 | break; |
| 2005 | 2008 | ||
| 2006 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 2009 | skb_queue_tail(&sdata->skb_queue, rx->skb); |
| 2010 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
| 2011 | return RX_QUEUED; | ||
| 2007 | } | 2012 | } |
| 2008 | break; | 2013 | break; |
| 2009 | case WLAN_CATEGORY_SA_QUERY: | 2014 | case WLAN_CATEGORY_SA_QUERY: |
| @@ -2021,9 +2026,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 2021 | break; | 2026 | break; |
| 2022 | case WLAN_CATEGORY_MESH_PLINK: | 2027 | case WLAN_CATEGORY_MESH_PLINK: |
| 2023 | case WLAN_CATEGORY_MESH_PATH_SEL: | 2028 | case WLAN_CATEGORY_MESH_PATH_SEL: |
| 2024 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2029 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
| 2025 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | 2030 | break; |
| 2026 | break; | 2031 | skb_queue_tail(&sdata->skb_queue, rx->skb); |
| 2032 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
| 2033 | return RX_QUEUED; | ||
| 2027 | } | 2034 | } |
| 2028 | 2035 | ||
| 2029 | /* | 2036 | /* |
| @@ -2080,10 +2087,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
| 2080 | { | 2087 | { |
| 2081 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2088 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
| 2082 | ieee80211_rx_result rxs; | 2089 | ieee80211_rx_result rxs; |
| 2090 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; | ||
| 2091 | __le16 stype; | ||
| 2083 | 2092 | ||
| 2084 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 2093 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
| 2085 | return RX_DROP_MONITOR; | 2094 | return RX_DROP_MONITOR; |
| 2086 | 2095 | ||
| 2096 | if (rx->skb->len < 24) | ||
| 2097 | return RX_DROP_MONITOR; | ||
| 2098 | |||
| 2087 | if (ieee80211_drop_unencrypted_mgmt(rx)) | 2099 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
| 2088 | return RX_DROP_UNUSABLE; | 2100 | return RX_DROP_UNUSABLE; |
| 2089 | 2101 | ||
| @@ -2091,16 +2103,39 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
| 2091 | if (rxs != RX_CONTINUE) | 2103 | if (rxs != RX_CONTINUE) |
| 2092 | return rxs; | 2104 | return rxs; |
| 2093 | 2105 | ||
| 2094 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2106 | stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); |
| 2095 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | ||
| 2096 | 2107 | ||
| 2097 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 2108 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
| 2098 | return ieee80211_ibss_rx_mgmt(sdata, rx->skb); | 2109 | sdata->vif.type != NL80211_IFTYPE_ADHOC && |
| 2110 | sdata->vif.type != NL80211_IFTYPE_STATION) | ||
| 2111 | return RX_DROP_MONITOR; | ||
| 2099 | 2112 | ||
| 2100 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 2113 | switch (stype) { |
| 2101 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 2114 | case cpu_to_le16(IEEE80211_STYPE_BEACON): |
| 2115 | case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): | ||
| 2116 | /* process for all: mesh, mlme, ibss */ | ||
| 2117 | break; | ||
| 2118 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
| 2119 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): | ||
| 2120 | /* process only for station */ | ||
| 2121 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
| 2122 | return RX_DROP_MONITOR; | ||
| 2123 | break; | ||
| 2124 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): | ||
| 2125 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
| 2126 | /* process only for ibss */ | ||
| 2127 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
| 2128 | return RX_DROP_MONITOR; | ||
| 2129 | break; | ||
| 2130 | default: | ||
| 2131 | return RX_DROP_MONITOR; | ||
| 2132 | } | ||
| 2102 | 2133 | ||
| 2103 | return RX_DROP_MONITOR; | 2134 | /* queue up frame and kick off work to process it */ |
| 2135 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
| 2136 | ieee80211_queue_work(&rx->local->hw, &sdata->work); | ||
| 2137 | |||
| 2138 | return RX_QUEUED; | ||
| 2104 | } | 2139 | } |
| 2105 | 2140 | ||
| 2106 | static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, | 2141 | static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, |
