diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 137 |
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 | ||
1942 | static ieee80211_rx_result debug_noinline | 1942 | static ieee80211_rx_result debug_noinline |
1943 | ieee80211_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 | |||
1967 | static ieee80211_rx_result debug_noinline | ||
1943 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1968 | ieee80211_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 | |||
2100 | static ieee80211_rx_result debug_noinline | ||
2101 | ieee80211_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 | |||
2130 | static ieee80211_rx_result debug_noinline | ||
2131 | ieee80211_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 | ||
2116 | static ieee80211_rx_result debug_noinline | 2177 | static 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; |