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.c90
1 files changed, 57 insertions, 33 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c9755f3d986c..a177472adc13 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2,7 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -1855,23 +1855,28 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1855 struct ieee80211_local *local = rx->local; 1855 struct ieee80211_local *local = rx->local;
1856 struct ieee80211_sub_if_data *sdata = rx->sdata; 1856 struct ieee80211_sub_if_data *sdata = rx->sdata;
1857 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; 1857 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1858 struct sk_buff *nskb;
1858 int len = rx->skb->len; 1859 int len = rx->skb->len;
1859 1860
1860 if (!ieee80211_is_action(mgmt->frame_control)) 1861 if (!ieee80211_is_action(mgmt->frame_control))
1861 return RX_CONTINUE; 1862 return RX_CONTINUE;
1862 1863
1863 if (!rx->sta) 1864 if (!rx->sta)
1864 return RX_DROP_MONITOR; 1865 return RX_DROP_UNUSABLE;
1865 1866
1866 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 1867 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1867 return RX_DROP_MONITOR; 1868 return RX_DROP_UNUSABLE;
1868 1869
1869 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) 1870 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
1870 return RX_DROP_MONITOR; 1871 return RX_DROP_UNUSABLE;
1871 1872
1872 /* all categories we currently handle have action_code */ 1873 /* drop too small frames */
1874 if (len < IEEE80211_MIN_ACTION_SIZE)
1875 return RX_DROP_UNUSABLE;
1876
1877 /* return action frames that have *only* category */
1873 if (len < IEEE80211_MIN_ACTION_SIZE + 1) 1878 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1874 return RX_DROP_MONITOR; 1879 goto return_frame;
1875 1880
1876 switch (mgmt->u.action.category) { 1881 switch (mgmt->u.action.category) {
1877 case WLAN_CATEGORY_BACK: 1882 case WLAN_CATEGORY_BACK:
@@ -1884,7 +1889,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1884 if (sdata->vif.type != NL80211_IFTYPE_STATION && 1889 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
1885 sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1890 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
1886 sdata->vif.type != NL80211_IFTYPE_AP) 1891 sdata->vif.type != NL80211_IFTYPE_AP)
1887 return RX_DROP_MONITOR; 1892 break;
1888 1893
1889 switch (mgmt->u.action.u.addba_req.action_code) { 1894 switch (mgmt->u.action.u.addba_req.action_code) {
1890 case WLAN_ACTION_ADDBA_REQ: 1895 case WLAN_ACTION_ADDBA_REQ:
@@ -1892,45 +1897,45 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1892 sizeof(mgmt->u.action.u.addba_req))) 1897 sizeof(mgmt->u.action.u.addba_req)))
1893 return RX_DROP_MONITOR; 1898 return RX_DROP_MONITOR;
1894 ieee80211_process_addba_request(local, rx->sta, mgmt, len); 1899 ieee80211_process_addba_request(local, rx->sta, mgmt, len);
1895 break; 1900 goto handled;
1896 case WLAN_ACTION_ADDBA_RESP: 1901 case WLAN_ACTION_ADDBA_RESP:
1897 if (len < (IEEE80211_MIN_ACTION_SIZE + 1902 if (len < (IEEE80211_MIN_ACTION_SIZE +
1898 sizeof(mgmt->u.action.u.addba_resp))) 1903 sizeof(mgmt->u.action.u.addba_resp)))
1899 return RX_DROP_MONITOR; 1904 break;
1900 ieee80211_process_addba_resp(local, rx->sta, mgmt, len); 1905 ieee80211_process_addba_resp(local, rx->sta, mgmt, len);
1901 break; 1906 goto handled;
1902 case WLAN_ACTION_DELBA: 1907 case WLAN_ACTION_DELBA:
1903 if (len < (IEEE80211_MIN_ACTION_SIZE + 1908 if (len < (IEEE80211_MIN_ACTION_SIZE +
1904 sizeof(mgmt->u.action.u.delba))) 1909 sizeof(mgmt->u.action.u.delba)))
1905 return RX_DROP_MONITOR; 1910 break;
1906 ieee80211_process_delba(sdata, rx->sta, mgmt, len); 1911 ieee80211_process_delba(sdata, rx->sta, mgmt, len);
1907 break; 1912 goto handled;
1908 } 1913 }
1909 break; 1914 break;
1910 case WLAN_CATEGORY_SPECTRUM_MGMT: 1915 case WLAN_CATEGORY_SPECTRUM_MGMT:
1911 if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) 1916 if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
1912 return RX_DROP_MONITOR; 1917 break;
1913 1918
1914 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1919 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1915 return RX_DROP_MONITOR; 1920 break;
1916 1921
1917 switch (mgmt->u.action.u.measurement.action_code) { 1922 switch (mgmt->u.action.u.measurement.action_code) {
1918 case WLAN_ACTION_SPCT_MSR_REQ: 1923 case WLAN_ACTION_SPCT_MSR_REQ:
1919 if (len < (IEEE80211_MIN_ACTION_SIZE + 1924 if (len < (IEEE80211_MIN_ACTION_SIZE +
1920 sizeof(mgmt->u.action.u.measurement))) 1925 sizeof(mgmt->u.action.u.measurement)))
1921 return RX_DROP_MONITOR; 1926 break;
1922 ieee80211_process_measurement_req(sdata, mgmt, len); 1927 ieee80211_process_measurement_req(sdata, mgmt, len);
1923 break; 1928 goto handled;
1924 case WLAN_ACTION_SPCT_CHL_SWITCH: 1929 case WLAN_ACTION_SPCT_CHL_SWITCH:
1925 if (len < (IEEE80211_MIN_ACTION_SIZE + 1930 if (len < (IEEE80211_MIN_ACTION_SIZE +
1926 sizeof(mgmt->u.action.u.chan_switch))) 1931 sizeof(mgmt->u.action.u.chan_switch)))
1927 return RX_DROP_MONITOR; 1932 break;
1928 1933
1929 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1934 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1930 return RX_DROP_MONITOR; 1935 break;
1931 1936
1932 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) 1937 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
1933 return RX_DROP_MONITOR; 1938 break;
1934 1939
1935 return ieee80211_sta_rx_mgmt(sdata, rx->skb); 1940 return ieee80211_sta_rx_mgmt(sdata, rx->skb);
1936 } 1941 }
@@ -1938,29 +1943,48 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1938 case WLAN_CATEGORY_SA_QUERY: 1943 case WLAN_CATEGORY_SA_QUERY:
1939 if (len < (IEEE80211_MIN_ACTION_SIZE + 1944 if (len < (IEEE80211_MIN_ACTION_SIZE +
1940 sizeof(mgmt->u.action.u.sa_query))) 1945 sizeof(mgmt->u.action.u.sa_query)))
1941 return RX_DROP_MONITOR; 1946 break;
1947
1942 switch (mgmt->u.action.u.sa_query.action) { 1948 switch (mgmt->u.action.u.sa_query.action) {
1943 case WLAN_ACTION_SA_QUERY_REQUEST: 1949 case WLAN_ACTION_SA_QUERY_REQUEST:
1944 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1950 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1945 return RX_DROP_MONITOR; 1951 break;
1946 ieee80211_process_sa_query_req(sdata, mgmt, len); 1952 ieee80211_process_sa_query_req(sdata, mgmt, len);
1947 break; 1953 goto handled;
1948 case WLAN_ACTION_SA_QUERY_RESPONSE:
1949 /*
1950 * SA Query response is currently only used in AP mode
1951 * and it is processed in user space.
1952 */
1953 return RX_CONTINUE;
1954 } 1954 }
1955 break; 1955 break;
1956 default: 1956 }
1957 /* do not process rejected action frames */ 1957 return_frame:
1958 if (mgmt->u.action.category & 0x80) 1958 /*
1959 return RX_DROP_MONITOR; 1959 * For AP mode, hostapd is responsible for handling any action
1960 * frames that we didn't handle, including returning unknown
1961 * ones. For all other modes we will return them to the sender,
1962 * setting the 0x80 bit in the action category, as required by
1963 * 802.11-2007 7.3.1.11.
1964 */
1965 if (sdata->vif.type == NL80211_IFTYPE_AP ||
1966 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1967 return RX_DROP_MONITOR;
1960 1968
1961 return RX_CONTINUE; 1969 /* do not return rejected action frames */
1970 if (mgmt->u.action.category & 0x80)
1971 return RX_DROP_UNUSABLE;
1972
1973 nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0,
1974 GFP_ATOMIC);
1975 if (nskb) {
1976 struct ieee80211_mgmt *mgmt = (void *)nskb->data;
1977
1978 mgmt->u.action.category |= 0x80;
1979 memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
1980 memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN);
1981
1982 memset(nskb->cb, 0, sizeof(nskb->cb));
1983
1984 ieee80211_tx_skb(rx->sdata, nskb);
1962 } 1985 }
1963 1986
1987 handled:
1964 rx->sta->rx_packets++; 1988 rx->sta->rx_packets++;
1965 dev_kfree_skb(rx->skb); 1989 dev_kfree_skb(rx->skb);
1966 return RX_QUEUED; 1990 return RX_QUEUED;