aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2010-02-15 05:53:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-02-15 16:14:15 -0500
commit026331c4d9b526561ea96f95fac4bfc52b69e316 (patch)
treea82b0a92a7f03a1d151a9db123320689c73d98c7 /net/mac80211/rx.c
parent8404080568613d93ad7cf0a16dfb68459b42a264 (diff)
cfg80211/mac80211: allow registering for and sending action frames
This implements a new command to register for action frames that userspace wants to handle instead of the in-kernel rejection. It is then responsible for rejecting ones that it decided not to handle. There is no unregistration, but the socket can be closed for that. Frames that are not registered for will not be forwarded to userspace and will be rejected by the kernel, the cfg80211 API helps implementing that. Additionally, this patch adds a new command that allows doing action frame transmission from userspace. It can be used either to exchange action frames on the current operational channel (e.g., with the AP with which we are currently associated) or to exchange off-channel Public Action frames with the remain-on-channel command. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a177472adc13..a6080d8d72bb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1856,28 +1856,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
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 struct sk_buff *nskb;
1859 struct ieee80211_rx_status *status;
1859 int len = rx->skb->len; 1860 int len = rx->skb->len;
1860 1861
1861 if (!ieee80211_is_action(mgmt->frame_control)) 1862 if (!ieee80211_is_action(mgmt->frame_control))
1862 return RX_CONTINUE; 1863 return RX_CONTINUE;
1863 1864
1864 if (!rx->sta) 1865 /* drop too small frames */
1866 if (len < IEEE80211_MIN_ACTION_SIZE)
1865 return RX_DROP_UNUSABLE; 1867 return RX_DROP_UNUSABLE;
1866 1868
1867 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 1869 if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
1868 return RX_DROP_UNUSABLE; 1870 return RX_DROP_UNUSABLE;
1869 1871
1870 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) 1872 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1871 return RX_DROP_UNUSABLE; 1873 return RX_DROP_UNUSABLE;
1872 1874
1873 /* drop too small frames */ 1875 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
1874 if (len < IEEE80211_MIN_ACTION_SIZE)
1875 return RX_DROP_UNUSABLE; 1876 return RX_DROP_UNUSABLE;
1876 1877
1877 /* return action frames that have *only* category */
1878 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1879 goto return_frame;
1880
1881 switch (mgmt->u.action.category) { 1878 switch (mgmt->u.action.category) {
1882 case WLAN_CATEGORY_BACK: 1879 case WLAN_CATEGORY_BACK:
1883 /* 1880 /*
@@ -1891,6 +1888,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1891 sdata->vif.type != NL80211_IFTYPE_AP) 1888 sdata->vif.type != NL80211_IFTYPE_AP)
1892 break; 1889 break;
1893 1890
1891 /* verify action_code is present */
1892 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1893 break;
1894
1894 switch (mgmt->u.action.u.addba_req.action_code) { 1895 switch (mgmt->u.action.u.addba_req.action_code) {
1895 case WLAN_ACTION_ADDBA_REQ: 1896 case WLAN_ACTION_ADDBA_REQ:
1896 if (len < (IEEE80211_MIN_ACTION_SIZE + 1897 if (len < (IEEE80211_MIN_ACTION_SIZE +
@@ -1919,6 +1920,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1919 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1920 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1920 break; 1921 break;
1921 1922
1923 /* verify action_code is present */
1924 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1925 break;
1926
1922 switch (mgmt->u.action.u.measurement.action_code) { 1927 switch (mgmt->u.action.u.measurement.action_code) {
1923 case WLAN_ACTION_SPCT_MSR_REQ: 1928 case WLAN_ACTION_SPCT_MSR_REQ:
1924 if (len < (IEEE80211_MIN_ACTION_SIZE + 1929 if (len < (IEEE80211_MIN_ACTION_SIZE +
@@ -1954,7 +1959,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1954 } 1959 }
1955 break; 1960 break;
1956 } 1961 }
1957 return_frame: 1962
1958 /* 1963 /*
1959 * For AP mode, hostapd is responsible for handling any action 1964 * For AP mode, hostapd is responsible for handling any action
1960 * frames that we didn't handle, including returning unknown 1965 * frames that we didn't handle, including returning unknown
@@ -1966,6 +1971,20 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1966 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1971 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1967 return RX_DROP_MONITOR; 1972 return RX_DROP_MONITOR;
1968 1973
1974 /*
1975 * Getting here means the kernel doesn't know how to handle
1976 * it, but maybe userspace does ... include returned frames
1977 * so userspace can register for those to know whether ones
1978 * it transmitted were processed or returned.
1979 */
1980 status = IEEE80211_SKB_RXCB(rx->skb);
1981
1982 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1983 cfg80211_rx_action(rx->sdata->dev, status->freq,
1984 rx->skb->data, rx->skb->len,
1985 GFP_ATOMIC))
1986 goto handled;
1987
1969 /* do not return rejected action frames */ 1988 /* do not return rejected action frames */
1970 if (mgmt->u.action.category & 0x80) 1989 if (mgmt->u.action.category & 0x80)
1971 return RX_DROP_UNUSABLE; 1990 return RX_DROP_UNUSABLE;
@@ -1985,7 +2004,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1985 } 2004 }
1986 2005
1987 handled: 2006 handled:
1988 rx->sta->rx_packets++; 2007 if (rx->sta)
2008 rx->sta->rx_packets++;
1989 dev_kfree_skb(rx->skb); 2009 dev_kfree_skb(rx->skb);
1990 return RX_QUEUED; 2010 return RX_QUEUED;
1991} 2011}