aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c137
1 files changed, 96 insertions, 41 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 4fdbed58ca2f..aa41e382bbb3 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1940,13 +1940,36 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
1940} 1940}
1941 1941
1942static ieee80211_rx_result debug_noinline 1942static ieee80211_rx_result debug_noinline
1943ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
1944{
1945 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1946
1947 /*
1948 * From here on, look only at management frames.
1949 * Data and control frames are already handled,
1950 * and unknown (reserved) frames are useless.
1951 */
1952 if (rx->skb->len < 24)
1953 return RX_DROP_MONITOR;
1954
1955 if (!ieee80211_is_mgmt(mgmt->frame_control))
1956 return RX_DROP_MONITOR;
1957
1958 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1959 return RX_DROP_MONITOR;
1960
1961 if (ieee80211_drop_unencrypted_mgmt(rx))
1962 return RX_DROP_UNUSABLE;
1963
1964 return RX_CONTINUE;
1965}
1966
1967static ieee80211_rx_result debug_noinline
1943ieee80211_rx_h_action(struct ieee80211_rx_data *rx) 1968ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1944{ 1969{
1945 struct ieee80211_local *local = rx->local; 1970 struct ieee80211_local *local = rx->local;
1946 struct ieee80211_sub_if_data *sdata = rx->sdata; 1971 struct ieee80211_sub_if_data *sdata = rx->sdata;
1947 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; 1972 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1948 struct sk_buff *nskb;
1949 struct ieee80211_rx_status *status;
1950 int len = rx->skb->len; 1973 int len = rx->skb->len;
1951 1974
1952 if (!ieee80211_is_action(mgmt->frame_control)) 1975 if (!ieee80211_is_action(mgmt->frame_control))
@@ -1962,9 +1985,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1962 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 1985 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1963 return RX_DROP_UNUSABLE; 1986 return RX_DROP_UNUSABLE;
1964 1987
1965 if (ieee80211_drop_unencrypted_mgmt(rx))
1966 return RX_DROP_UNUSABLE;
1967
1968 switch (mgmt->u.action.category) { 1988 switch (mgmt->u.action.category) {
1969 case WLAN_CATEGORY_BACK: 1989 case WLAN_CATEGORY_BACK:
1970 /* 1990 /*
@@ -2055,17 +2075,36 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2055 goto queue; 2075 goto queue;
2056 } 2076 }
2057 2077
2078 return RX_CONTINUE;
2079
2058 invalid: 2080 invalid:
2059 /* 2081 rx->flags |= IEEE80211_MALFORMED_ACTION_FRM;
2060 * For AP mode, hostapd is responsible for handling any action 2082 /* will return in the next handlers */
2061 * frames that we didn't handle, including returning unknown 2083 return RX_CONTINUE;
2062 * ones. For all other modes we will return them to the sender, 2084
2063 * setting the 0x80 bit in the action category, as required by 2085 handled:
2064 * 802.11-2007 7.3.1.11. 2086 if (rx->sta)
2065 */ 2087 rx->sta->rx_packets++;
2066 if (sdata->vif.type == NL80211_IFTYPE_AP || 2088 dev_kfree_skb(rx->skb);
2067 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 2089 return RX_QUEUED;
2068 return RX_DROP_MONITOR; 2090
2091 queue:
2092 rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
2093 skb_queue_tail(&sdata->skb_queue, rx->skb);
2094 ieee80211_queue_work(&local->hw, &sdata->work);
2095 if (rx->sta)
2096 rx->sta->rx_packets++;
2097 return RX_QUEUED;
2098}
2099
2100static ieee80211_rx_result debug_noinline
2101ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
2102{
2103 struct ieee80211_rx_status *status;
2104
2105 /* skip known-bad action frames and return them in the next handler */
2106 if (rx->flags & IEEE80211_MALFORMED_ACTION_FRM)
2107 return RX_CONTINUE;
2069 2108
2070 /* 2109 /*
2071 * Getting here means the kernel doesn't know how to handle 2110 * Getting here means the kernel doesn't know how to handle
@@ -2075,10 +2114,44 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2075 */ 2114 */
2076 status = IEEE80211_SKB_RXCB(rx->skb); 2115 status = IEEE80211_SKB_RXCB(rx->skb);
2077 2116
2078 if (cfg80211_rx_action(rx->sdata->dev, status->freq, 2117 if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq,
2079 rx->skb->data, rx->skb->len, 2118 rx->skb->data, rx->skb->len,
2080 GFP_ATOMIC)) 2119 GFP_ATOMIC)) {
2081 goto handled; 2120 if (rx->sta)
2121 rx->sta->rx_packets++;
2122 dev_kfree_skb(rx->skb);
2123 return RX_QUEUED;
2124 }
2125
2126
2127 return RX_CONTINUE;
2128}
2129
2130static ieee80211_rx_result debug_noinline
2131ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
2132{
2133 struct ieee80211_local *local = rx->local;
2134 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
2135 struct sk_buff *nskb;
2136 struct ieee80211_sub_if_data *sdata = rx->sdata;
2137
2138 if (!ieee80211_is_action(mgmt->frame_control))
2139 return RX_CONTINUE;
2140
2141 /*
2142 * For AP mode, hostapd is responsible for handling any action
2143 * frames that we didn't handle, including returning unknown
2144 * ones. For all other modes we will return them to the sender,
2145 * setting the 0x80 bit in the action category, as required by
2146 * 802.11-2007 7.3.1.11.
2147 * Newer versions of hostapd shall also use the management frame
2148 * registration mechanisms, but older ones still use cooked
2149 * monitor interfaces so push all frames there.
2150 */
2151 if (!(rx->flags & IEEE80211_MALFORMED_ACTION_FRM) &&
2152 (sdata->vif.type == NL80211_IFTYPE_AP ||
2153 sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
2154 return RX_DROP_MONITOR;
2082 2155
2083 /* do not return rejected action frames */ 2156 /* do not return rejected action frames */
2084 if (mgmt->u.action.category & 0x80) 2157 if (mgmt->u.action.category & 0x80)
@@ -2097,20 +2170,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2097 2170
2098 ieee80211_tx_skb(rx->sdata, nskb); 2171 ieee80211_tx_skb(rx->sdata, nskb);
2099 } 2172 }
2100
2101 handled:
2102 if (rx->sta)
2103 rx->sta->rx_packets++;
2104 dev_kfree_skb(rx->skb); 2173 dev_kfree_skb(rx->skb);
2105 return RX_QUEUED; 2174 return RX_QUEUED;
2106
2107 queue:
2108 rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
2109 skb_queue_tail(&sdata->skb_queue, rx->skb);
2110 ieee80211_queue_work(&local->hw, &sdata->work);
2111 if (rx->sta)
2112 rx->sta->rx_packets++;
2113 return RX_QUEUED;
2114} 2175}
2115 2176
2116static ieee80211_rx_result debug_noinline 2177static ieee80211_rx_result debug_noinline
@@ -2121,15 +2182,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
2121 struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; 2182 struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
2122 __le16 stype; 2183 __le16 stype;
2123 2184
2124 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
2125 return RX_DROP_MONITOR;
2126
2127 if (rx->skb->len < 24)
2128 return RX_DROP_MONITOR;
2129
2130 if (ieee80211_drop_unencrypted_mgmt(rx))
2131 return RX_DROP_UNUSABLE;
2132
2133 rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); 2185 rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
2134 if (rxs != RX_CONTINUE) 2186 if (rxs != RX_CONTINUE)
2135 return rxs; 2187 return rxs;
@@ -2374,7 +2426,10 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
2374 if (res != RX_CONTINUE) 2426 if (res != RX_CONTINUE)
2375 goto rxh_next; 2427 goto rxh_next;
2376 2428
2429 CALL_RXH(ieee80211_rx_h_mgmt_check)
2377 CALL_RXH(ieee80211_rx_h_action) 2430 CALL_RXH(ieee80211_rx_h_action)
2431 CALL_RXH(ieee80211_rx_h_userspace_mgmt)
2432 CALL_RXH(ieee80211_rx_h_action_return)
2378 CALL_RXH(ieee80211_rx_h_mgmt) 2433 CALL_RXH(ieee80211_rx_h_mgmt)
2379 2434
2380 rxh_next: 2435 rxh_next:
@@ -2527,7 +2582,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
2527 break; 2582 break;
2528 case NL80211_IFTYPE_MONITOR: 2583 case NL80211_IFTYPE_MONITOR:
2529 case NL80211_IFTYPE_UNSPECIFIED: 2584 case NL80211_IFTYPE_UNSPECIFIED:
2530 case __NL80211_IFTYPE_AFTER_LAST: 2585 case NUM_NL80211_IFTYPES:
2531 /* should never get here */ 2586 /* should never get here */
2532 WARN_ON(1); 2587 WARN_ON(1);
2533 break; 2588 break;