2
2
* Copyright 2002-2005, Instant802 Networks, Inc.
3
3
* Copyright 2005-2006, Devicescape Software, Inc.
4
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
7
* This program is free software; you can redistribute it and/or modify
8
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
1855
struct ieee80211_local * local = rx -> local ;
1856
1856
struct ieee80211_sub_if_data * sdata = rx -> sdata ;
1857
1857
struct ieee80211_mgmt * mgmt = (struct ieee80211_mgmt * ) rx -> skb -> data ;
1858
+ struct sk_buff * nskb ;
1858
1859
int len = rx -> skb -> len ;
1859
1860
1860
1861
if (!ieee80211_is_action (mgmt -> frame_control ))
1861
1862
return RX_CONTINUE ;
1862
1863
1863
1864
if (!rx -> sta )
1864
- return RX_DROP_MONITOR ;
1865
+ return RX_DROP_UNUSABLE ;
1865
1866
1866
1867
if (!(rx -> flags & IEEE80211_RX_RA_MATCH ))
1867
- return RX_DROP_MONITOR ;
1868
+ return RX_DROP_UNUSABLE ;
1868
1869
1869
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
1878
if (len < IEEE80211_MIN_ACTION_SIZE + 1 )
1874
- return RX_DROP_MONITOR ;
1879
+ goto return_frame ;
1875
1880
1876
1881
switch (mgmt -> u .action .category ) {
1877
1882
case WLAN_CATEGORY_BACK :
@@ -1884,83 +1889,102 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1884
1889
if (sdata -> vif .type != NL80211_IFTYPE_STATION &&
1885
1890
sdata -> vif .type != NL80211_IFTYPE_AP_VLAN &&
1886
1891
sdata -> vif .type != NL80211_IFTYPE_AP )
1887
- return RX_DROP_MONITOR ;
1892
+ break ;
1888
1893
1889
1894
switch (mgmt -> u .action .u .addba_req .action_code ) {
1890
1895
case WLAN_ACTION_ADDBA_REQ :
1891
1896
if (len < (IEEE80211_MIN_ACTION_SIZE +
1892
1897
sizeof (mgmt -> u .action .u .addba_req )))
1893
1898
return RX_DROP_MONITOR ;
1894
1899
ieee80211_process_addba_request (local , rx -> sta , mgmt , len );
1895
- break ;
1900
+ goto handled ;
1896
1901
case WLAN_ACTION_ADDBA_RESP :
1897
1902
if (len < (IEEE80211_MIN_ACTION_SIZE +
1898
1903
sizeof (mgmt -> u .action .u .addba_resp )))
1899
- return RX_DROP_MONITOR ;
1904
+ break ;
1900
1905
ieee80211_process_addba_resp (local , rx -> sta , mgmt , len );
1901
- break ;
1906
+ goto handled ;
1902
1907
case WLAN_ACTION_DELBA :
1903
1908
if (len < (IEEE80211_MIN_ACTION_SIZE +
1904
1909
sizeof (mgmt -> u .action .u .delba )))
1905
- return RX_DROP_MONITOR ;
1910
+ break ;
1906
1911
ieee80211_process_delba (sdata , rx -> sta , mgmt , len );
1907
- break ;
1912
+ goto handled ;
1908
1913
}
1909
1914
break ;
1910
1915
case WLAN_CATEGORY_SPECTRUM_MGMT :
1911
1916
if (local -> hw .conf .channel -> band != IEEE80211_BAND_5GHZ )
1912
- return RX_DROP_MONITOR ;
1917
+ break ;
1913
1918
1914
1919
if (sdata -> vif .type != NL80211_IFTYPE_STATION )
1915
- return RX_DROP_MONITOR ;
1920
+ break ;
1916
1921
1917
1922
switch (mgmt -> u .action .u .measurement .action_code ) {
1918
1923
case WLAN_ACTION_SPCT_MSR_REQ :
1919
1924
if (len < (IEEE80211_MIN_ACTION_SIZE +
1920
1925
sizeof (mgmt -> u .action .u .measurement )))
1921
- return RX_DROP_MONITOR ;
1926
+ break ;
1922
1927
ieee80211_process_measurement_req (sdata , mgmt , len );
1923
- break ;
1928
+ goto handled ;
1924
1929
case WLAN_ACTION_SPCT_CHL_SWITCH :
1925
1930
if (len < (IEEE80211_MIN_ACTION_SIZE +
1926
1931
sizeof (mgmt -> u .action .u .chan_switch )))
1927
- return RX_DROP_MONITOR ;
1932
+ break ;
1928
1933
1929
1934
if (sdata -> vif .type != NL80211_IFTYPE_STATION )
1930
- return RX_DROP_MONITOR ;
1935
+ break ;
1931
1936
1932
1937
if (memcmp (mgmt -> bssid , sdata -> u .mgd .bssid , ETH_ALEN ))
1933
- return RX_DROP_MONITOR ;
1938
+ break ;
1934
1939
1935
1940
return ieee80211_sta_rx_mgmt (sdata , rx -> skb );
1936
1941
}
1937
1942
break ;
1938
1943
case WLAN_CATEGORY_SA_QUERY :
1939
1944
if (len < (IEEE80211_MIN_ACTION_SIZE +
1940
1945
sizeof (mgmt -> u .action .u .sa_query )))
1941
- return RX_DROP_MONITOR ;
1946
+ break ;
1947
+
1942
1948
switch (mgmt -> u .action .u .sa_query .action ) {
1943
1949
case WLAN_ACTION_SA_QUERY_REQUEST :
1944
1950
if (sdata -> vif .type != NL80211_IFTYPE_STATION )
1945
- return RX_DROP_MONITOR ;
1951
+ break ;
1946
1952
ieee80211_process_sa_query_req (sdata , mgmt , len );
1947
- break ;
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 ;
1953
+ goto handled ;
1954
1954
}
1955
1955
break ;
1956
- default :
1957
- /* do not process rejected action frames */
1958
- if (mgmt -> u .action .category & 0x80 )
1959
- return RX_DROP_MONITOR ;
1956
+ }
1957
+ return_frame :
1958
+ /*
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
1988
rx -> sta -> rx_packets ++ ;
1965
1989
dev_kfree_skb (rx -> skb );
1966
1990
return RX_QUEUED ;
0 commit comments